#pragma once #include "local_tasks.h" #include #include #include #include namespace NBus { namespace NPrivate { template class TScheduleActor { typedef NActor::TActor TActorForMe; private: TScheduler* const Scheduler; TMutex Mutex; TInstant ScheduleTime; public: TLocalTasks Alarm; private: struct TScheduleItemImpl: public IScheduleItem { TIntrusivePtr Thiz; TScheduleItemImpl(TIntrusivePtr thiz, TInstant when) : IScheduleItem(when) , Thiz(thiz) { } void Do() override { { TWhatThreadDoesAcquireGuard guard(Thiz->Mutex, "scheduler actor: acquiring lock for Do"); if (Thiz->ScheduleTime == TInstant::Max()) { // was already fired return; } Thiz->ScheduleTime = TInstant::Max(); } Thiz->Alarm.AddTask(); Thiz->GetActorForMe()->Schedule(); } }; public: TScheduleActor(TScheduler* scheduler) : Scheduler(scheduler) , ScheduleTime(TInstant::Max()) { } /// call Act(TTag) at specified time, unless it is already scheduled at earlier time. void ScheduleAt(TInstant when) { TWhatThreadDoesAcquireGuard guard(Mutex, "scheduler: acquiring lock for ScheduleAt"); if (when > ScheduleTime) { // already scheduled return; } ScheduleTime = when; Scheduler->Schedule(new TScheduleItemImpl(GetThis(), when)); } private: TThis* GetThis() { return static_cast(this); } TActorForMe* GetActorForMe() { return static_cast(GetThis()); } }; } }