// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include #include #include #include namespace System { struct NativeContextGroup; struct NativeContext { void* ucontext; void* stackPtr; bool interrupted; NativeContext* next; NativeContextGroup* group; NativeContext* groupPrev; NativeContext* groupNext; std::function procedure; std::function interruptProcedure; }; struct NativeContextGroup { NativeContext* firstContext; NativeContext* lastContext; NativeContext* firstWaiter; NativeContext* lastWaiter; }; struct OperationContext { NativeContext *context; bool interrupted; uint32_t events; }; struct ContextPair { OperationContext *readContext; OperationContext *writeContext; }; class Dispatcher { public: Dispatcher(); Dispatcher(const Dispatcher&) = delete; ~Dispatcher(); Dispatcher& operator=(const Dispatcher&) = delete; void clear(); void dispatch(); NativeContext* getCurrentContext() const; void interrupt(); void interrupt(NativeContext* context); bool interrupted(); void pushContext(NativeContext* context); void remoteSpawn(std::function&& procedure); void yield(); // system-dependent int getEpoll() const; NativeContext& getReusableContext(); void pushReusableContext(NativeContext&); int getTimer(); void pushTimer(int timer); #ifdef __x86_64__ # if __WORDSIZE == 64 static const int SIZEOF_PTHREAD_MUTEX_T = 40; # else static const int SIZEOF_PTHREAD_MUTEX_T = 32; # endif #else static const int SIZEOF_PTHREAD_MUTEX_T = 24; #endif private: void spawn(std::function&& procedure); int epoll; alignas(void*) uint8_t mutex[SIZEOF_PTHREAD_MUTEX_T]; int remoteSpawnEvent; ContextPair remoteSpawnEventContext; std::queue> remoteSpawningProcedures; std::stack timers; NativeContext mainContext; NativeContextGroup contextGroup; NativeContext* currentContext; NativeContext* firstResumingContext; NativeContext* lastResumingContext; NativeContext* firstReusableContext; size_t runningContextCount; void contextProcedure(void* ucontext); static void contextProcedureStatic(void* context); }; }