#ifndef DDK_THREAD #define DDK_THREAD 1 #include #include #include #include extern "C" void InterceptorThreadRoutine(PVOID threadContext); namespace DriverThread { class Mutex { public: Mutex(void); ~Mutex(void); private: void Lock(); void Unlock(); volatile long int m_interlock; friend class LockGuard; }; class LockGuard { public: LockGuard(Mutex & m); ~LockGuard(void); private: Mutex m_Lock; }; class ThreadArgs : public virtual eastl::enable_shared_from_this { public: ThreadArgs(void) { } ThreadArgs(const ThreadArgs &) = delete; virtual ~ThreadArgs(void) { } }; using ThreadRoutine = eastl::function args)>; class Thread { public: Thread(void); Thread(const Thread &) = delete; ~Thread(void); NTSTATUS Start(ThreadRoutine routine, eastl::shared_ptr args); NTSTATUS WaitForTermination(LONGLONG timeout = 0); HANDLE GetThreadId(void) { return m_threadId; } bool isRunning(void) { return GetThreadId() != nullptr; } private: friend void ::InterceptorThreadRoutine(PVOID threadContext); HANDLE m_threadId = nullptr; PETHREAD m_threadObject = nullptr; Mutex m_mutex; ThreadRoutine m_routine; eastl::shared_ptr m_threadContext; }; class Spinlock { public: Spinlock(void); NTSTATUS Acquire(void); void Release(void); KIRQL GetOldIrql(void); private: KIRQL m_oldIrql; KSPIN_LOCK m_spinLock; }; class Semaphore { public: Semaphore(LONG initialValue = 0, LONG maxValue = MAXLONG); NTSTATUS Wait(LONGLONG timeout = 0); LONG Release(LONG adjustment = 1); private: KSEMAPHORE m_semaphore; }; class Event { public: Event(); NTSTATUS Wait(LONGLONG timeout = 0); NTSTATUS Notify(); private: KEVENT m_event; }; class WorkItem final { friend class WorkQueue; public: WorkItem(const eastl::shared_ptr & user) : m_user(std::move(user)) { } virtual ~WorkItem(void) { } template eastl::shared_ptr Get(void) { return eastl::static_pointer_cast(m_user); } template void Get(eastl::shared_ptr & dest) { dest = eastl::static_pointer_cast(m_user); } private: eastl::shared_ptr m_user; }; using WorkerRoutine = eastl::function; class WorkQueue final { public: WorkQueue(void); WorkQueue(const WorkQueue &) = delete; ~WorkQueue(void); NTSTATUS Start(WorkerRoutine routine); void Stop(bool wait = true); void Enqueue(WorkItem & item); void Enqueue(eastl::deque & items); private: Mutex m_mutex; eastl::deque m_queue; Event m_wakeEvent; bool m_stopWorker; // Work LIST must be empty and StopWorker TRUE to be able to stop! Thread m_worker; WorkerRoutine m_workerRoutine; static NTSTATUS WorkerInterceptorRoutine(eastl::shared_ptr args); }; }; // namespace DriverThread #endif