/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* RCThread.h */ #if defined(_RCTHREAD_H) #else #define _RCTHREAD_H #include "rcbase.h" #include class RCInterval; class PR_IMPLEMENT(RCThreadPrivateData) { public: RCThreadPrivateData(); RCThreadPrivateData(const RCThreadPrivateData&); virtual ~RCThreadPrivateData(); virtual void Release() = 0; }; /* RCThreadPrivateData */ class PR_IMPLEMENT(RCThread): public RCBase { public: typedef enum { local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD } Scope; typedef enum { joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD } State; typedef enum { first = PR_PRIORITY_FIRST, low = PR_PRIORITY_LOW, normal = PR_PRIORITY_NORMAL, high = PR_PRIORITY_HIGH, urgent = PR_PRIORITY_URGENT, last = PR_PRIORITY_LAST } Priority; /* * Create a new thread, providing scope and joinability state. */ RCThread(Scope scope, State state, PRUint32 stackSize=0); /* * New threads are created in a suspended state. It must be 'started" * before it begins execution in the class' defined 'RootFunction()'. */ virtual PRStatus Start(); /* * If a thread is created joinable, then the thread's object exists * until join is called. The thread that calls join will block until * the target thread returns from it's root function. */ virtual PRStatus Join(); /* * The priority of a newly created thread is the same as the creator. * The priority may be changed either by the new thread itself, by * the creator or any other arbitrary thread. */ virtual void SetPriority(Priority newPriority); /* * Interrupt another thread, causing it to stop what it * is doing and return with a well known error code. */ virtual PRStatus Interrupt(); /* * And in case a thread was interrupted and didn't get a chance * to have the notification delivered, a way to cancel the pending * status. */ static void ClearInterrupt(); /* * Methods to discover the attributes of an existing thread. */ static PRThread *Self(); Scope GetScope() const; State GetState() const; Priority GetPriority() const; /* * Thread private data */ static PRStatus NewPrivateIndex(PRUintn* index); /* * Getting it - if you want to modify, make a copy */ static RCThreadPrivateData* GetPrivateData(PRUintn index); /* * Setting it to - deletes existing data */ static PRStatus SetPrivateData(PRUintn index); /* * Setting it - runtime will make a copy, freeing old iff necessary */ static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data); /* * Scheduling control */ static PRStatus Sleep(const RCInterval& ticks); friend void nas_Root(void*); friend class RCPrimordialThread; protected: /* * The instantiator of a class must not call the destructor. The base * implementation of Join will, and if the thread is created unjoinable, * then the code that called the RootFunction will call the desctructor. */ virtual ~RCThread(); private: /* * This is where a newly created thread begins execution. Returning * from this function is equivalent to terminating the thread. */ virtual void RootFunction() = 0; PRThread *identity; /* Threads are unstarted until started - pretty startling */ enum {ex_unstarted, ex_started} execution; /* There is no public default constructor or copy constructor */ RCThread(); RCThread(const RCThread&); /* And there is no assignment operator */ void operator=(const RCThread&); public: static RCPrimordialThread *WrapPrimordialThread(); }; /* ** class RCPrimordialThread */ class PR_IMPLEMENT(RCPrimordialThread): public RCThread { public: /* ** The primordial thread can (optionally) wait for all created ** threads to terminate before allowing the process to exit. ** Not calling Cleanup() before returning from main() will cause ** the immediate termination of the entire process, including ** any running threads. */ static PRStatus Cleanup(); /* ** Only the primordial thread is allowed to adjust the number of ** virtual processors of the runtime. It's a lame security thing. */ static PRStatus SetVirtualProcessors(PRIntn count=10); friend class RCThread; private: /* ** None other than the runtime can create of destruct ** a primordial thread. It is fabricated by the runtime ** to wrap the thread that initiated the application. */ RCPrimordialThread(); ~RCPrimordialThread(); void RootFunction(); }; /* RCPrimordialThread */ #endif /* defined(_RCTHREAD_H) */