Root/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | < html > <!-- #BeginTemplate "/Templates/tmpl.dwt" --> <!-- DW6 --> < head > <!-- #BeginEditable "doctitle" --> < title >PTypes: multithreading: thread</ title > <!-- #EndEditable --> < meta http-equiv = "Content-Type" content = "text/html; charset=iso-8859-1" > < link rel = "stylesheet" href = "styles.css" > </ head > < body bgcolor = "#FFFFFF" leftmargin = "40" marginwidth = "40" > < p >< a href = "../index.html" >< img src = "title-21.png" width = "253" height = "39" alt = "C++ Portable Types Library (PTypes) Version 2.1" border = "0" ></ a > < hr size = "1" noshade> <!-- #BeginEditable "body" --> < p class = "hpath" >< a href = "index.html" >Top</ a >: < a href = "async.html" >Multithreading</ a >: thread </ p > < blockquote > < pre class = "lang" >#include < pasync.h > class thread { thread(bool autofree); ~thread(); void start(); void waitfor(); void signal(); pthread_id_t get_id(); bool get_running(); bool get_finished(); bool get_signaled(); virtual void execute() = 0; virtual void cleanup() = 0; bool relax(int milliseconds); }</ pre > </ blockquote > < p >Create a descendant of < span class = "lang" >thread</ span > to represent an execution thread in a multithreaded application. All threads are running within the framework of the parent process and share the same global variables. Each thread, however, has its own stack. The execution of a thread can be started either from the main process or from another thread. Further, the newly launched thread executes its code concurrently.</ p > < p >Multithreading can significantly improve your application when a process consumes time by waiting for data from some communication device, a slow storage device or user input. When such pieces of code run concurrently the CPU is loaded more efficiently. Also, many networking services use threading to serve multiple users simultaneously.</ p > < p >When threads concurrently access and modify shared data structures precautions should be taken to preserve logical integrity of these data structures. Synchronization between threads is performed using either of: < a href = "async.semaphore.html" >semaphore</ a >, < a href = "async.mutex.html" >mutex</ a >, < a href = "async.rwlock.html" >rwlock</ a >, < a href = "async.trigger.html" >trigger</ a > or < a href = "async.msgqueue.html" >msgqueue</ a >.</ p > < p >< span class = "def" >thread::thread(bool autofree)</ span > creates a thread object, but does not run it. If < span class = "lang" >autofree</ span > is < span class = "lang" >true</ span > the thread will destroy itself upon termination. Note, that you can use < span class = "lang" >autofree</ span > only for dynamically allocated thread objects. A variable that holds a pointer to a dynamic < span class = "lang" >autofree</ span > thread object can be considered invalid after a call to < span class = "lang" >start()</ span >.</ p > < p >< span class = "def" >thread::~thread()</ span > destroys the thread object. Usually both the constructor and the destructor for non-autofree threads are called from a different context. In contrary, autofree threads call their destructors from their own context.</ p > < p >< span class = "def" >void thread::start()</ span > runs the thread. The overridden virtual method < span class = "lang" >execute()</ span > is called asynchronously. < span class = "lang" >Start()</ span > itself returns immediately. Each thread object can be run only once.</ p > < p >< span class = "def" >void thread::waitfor()</ span > waits for the thread to terminate. This function is called when a thread needs to synchronize its execution with the completion of the target non-autofree thread. For non-autofree threads this method must be called < b >at least once</ b > and within the scope of a thread that called < span class = "lang" >start()</ span >. For convenience, you can place a call to < span class = "lang" >waitfor()</ span > in the overridden destructor. < span class = "lang" >waitfor()</ span >, however, can not be called for autofree threads.</ p > < p >< span class = "def" >void thread::signal()</ span > sets signaled attribute to true and possibly wakes up the thread if in a `relaxed' state (see < span class = "lang" >relax()</ span > below). < span class = "lang" >signal()</ span > is usually called from a different thread to let the given thread know that the execution should be terminated as soon as possible. If the given thread performs an iteration one of the conditions of leaving the loop should be < span class = "lang" >(!get_signaled())</ span >. < span class = "lang" >Signal()</ span > can be called only once for a thread object.</ p > < p >< span class = "def" >pthread_id_t thread::get_id()</ span > returns the thread ID assigned by the operating system. This ID can then be used in call to < span class = "lang" >pthrequal()</ span >.</ p > < p >< span class = "def" >bool thread::get_running()</ span > returns < span class = "lang" >true</ span > if the given thread object is running. This property is never set to < span class = "lang" >false</ span > once the thread started. To check whether the thread finished its job, i.e. returned from < span class = "lang" >execute()</ span >, use < span class = "lang" >get_finished()</ span >.</ p > < p >< span class = "def" >bool thread::get_finished()</ span > returns < span class = "lang" >true</ span > if thread has already terminated its execution, or, in other words, has left < span class = "lang" >execute()</ span >.</ p > < p >< span class = "def" >bool thread::get_signaled()</ span > returns < span class = "lang" >true</ span > if the thread object is in signaled state, i.e. < span class = "lang" >signal()</ span > has been called from a concurrent thread. See also < span class = "lang" >signal()</ span >.</ p > < p >< span class = "def" >virtual void thread::execute()</ span > -- this pure virtual method should be overridden in the descendant class to implement the functionality of your thread. < span class = "lang" >execute()</ span > can be viewed as < span class = "lang" >main()</ span > for your mini-process. Typically, you create a class descendant from < span class = "lang" >thread</ span > and override at least two virtual methods: < span class = "lang" >execute()</ span > and < span class = "lang" >cleanup()</ span >.</ p > < p >< span class = "def" >virtual void thread::cleanup()</ span > -- this pure virtual method should be overridden in the descendant class. < span class = "lang" >cleanup()</ span > is called either when the thread terminates normally or when an exception is raised within the thread's context. When implementing this method you might want to clean up any memory and other resources allocated by your thread object. < span class = "lang" >cleanup()</ span > is guaranteed to be called once upon termination of the thread. To properly shut down the thread, avoid using operations that can cause exceptions in < span class = "lang" >cleanup()</ span >.</ p > < p >< span class = "def" >bool thread::relax(int milliseconds)</ span > is a protected member function which can be called only from within the overridden < span class = "lang" >execute()</ span > method. This function suspends the execution of the thread until either of: the specified amount of time is elapsed, in which case the function returns false, or < span class = "lang" >signal()</ span > is called from a concurrent thread, in which case < span class = "lang" >relax()</ span > returns true. If parameter < span class = "lang" >milliseconds</ span > is -1 the function will wait infinitely. The relax/signal mechanism is useful for threads doing some job that requires taking periodic actions in the background.</ p > < p class = "seealso" >See also: < a href = "async.semaphore.html" >semaphore</ a >, < a href = "async.examples.html" >mutex</ a >, < a href = "async.rwlock.html" >rwlock</ a >, < a href = "async.trigger.html" >trigger</ a >, < a href = "async.utils.html" >Utilities</ a >, < a href = "async.examples.html" >Examples</ a ></ p > <!-- #EndEditable --> < hr size = "1" > < a href = "../index.html" class = "ns" >PTypes home</ a > </ body > <!-- #EndTemplate --> </ html > |
Source at commit 209d6fa3805c created 11 years 11 months ago. By Nathan Adams, Updating tparray to use variants as array because tpodlist was causing variant data corruption |
---|