Contents
CThread
class written in Microsoft Visual C++ is a wrapper class
that constitutes the base for the comfortable Windows worker thread handling in
the MFC environment. CThread
itself is an abstract class from which user
thread-specific classes have to be derived. CThread
class offers
the opportunities how to define, implement and handle thread objects. Most
functionality is done in this base class, a developer is just responsible to
implement a thread-specific task and handle incoming notifications fired from
the owner of the thread. CThread
class is fully compliant to the
Object-Oriented Paradigm.
CThread
abstract class defines conception describing the main
requirements regarding the thread handling. There are two main paradigms
concerning thread task implementation:
Thread task is a simple sequence of commands that are to be done. After
starting the thread, the thread terminates after completing the whole task.
Owner thread (typically the main application thread) may communicate with a
CThread
thread by some intermediate object visible for both sides.
This communication, however, does not provide effective parent-child-thread
notifications. Maintaining all risky situations originating in such
communication requires an additional developer's effort. Using of this
conception is recommended for linear or straightforward heavyweight tasks, more
or less independent from the owner thread that do not require sophisticated or
intensive communication with the owner thread. CThread
thread
supporting this paradigm is called Trivial Thread.
In opposite to Trivial Threads, the thread task may be application-sensitive
and listens to the owner thread commands. In this case the thread task is a loop
in which thread waits for incoming notifications (commands). After receiving a
command the thread executes this command. Incoming commands are handled
sequentially in the thread task procedure. Simultaneously, the thread may set
the current thread activity status to inform the owner thread.
Notificable Threads act as 'schedulers' or 'services'. That means, these
threads execute their task on the owner thread demand and wait for another
command. Usually the task executed in such thread should not be too long to
allow an owner thread to make an effective controlling over the thread. This
thread is called Notificable Thread.
CThread
class supports both paradigms but emphasizes developers
to use Notificable Threads.
CThread
derived classes may utilize the special synchronization
feature that is implemented in the basic CThread
class. The
mentioned Thread-Handler-Oriented Synchronization is a powerful feature provided
by CThread
class. Developers do not have to deal too much with
synchronization among thread objects using the same thread-task handler (the
ThreadHandler()
method). They just use Lock()
or Unlock()
CThread
methods to lock the critical code that is to be executed exclusively in
the ThreadHandler()
method. Developers may, however, omit this synchronization
feature and define the CThread
derived class, which does not
support this kind of synchronization. It is up to the developer�s responsibility
to implement non-critical thread task or instantiate just one thread object in
such case.
Each CThread
derived class requiring its own
Thread-Handler-Oriented Synchronization must declare this feature explicitly
(this can be automatically established while working with Worker Thread Class
Generator Wizard).
This kind of synchronization is so-called Thread-Handler-Oriented. Suppose a
developer utilizes two CThread
derived classes
CThreadDerived1
and CThreadDerived2
and each class
implements its own ThreadHandler()
method. Let Thread11
and Thread12
are the instantiated objects of the class
CThreadDerived1
and Thread21 and Thread22 are the objects of the class
CThreadDerived2
. Thread11 is synchronized with Thread12 but not
with Thread21 or Thread22 and vice versa. All thread objects of the
CThreadDerived1
class are synchronized among each other (as well as all objects
of the CThreadDerived2
class) but the synchronization of CThreadDerived1
objects
is fully independent from the synchronization of CThreadDerived2
objects.
On the other hand, if the CThreadDerived3
class is derived from
the CThreadDerived2
but do not implement its own
ThreadHandler()
method (uses the handler implemented in the
CThreadDerived2
class), the CThreadDerived3
objects
are automatically synchronized with the CThreadDerived2
objects and
vice versa.
In a CThread
object-oriented hierarchy developers may design
several CThread
-derived classes for different purposes. Some of
them will implement the specific thread-task handlers the others will inherit
them. Thread-Handler-Oriented Synchronization allows developers to split
CThread
objects into the groups that contain CThread
-derived objects operating on the same thread-task handler. Thus, each
group defines its own thread-task handler and logically provides the
synchronization for all objects belonging to this group. On the other hand,
another group operates on a different thread-task handler, executing a
completely different task independent from another group, so the synchronization
has also to be independent from another group. Thread-Handler-Oriented
Synchronization establishes and maintains the independent synchronization for
each group automatically. All the developer has to do is to write the
SUPPORT_THREAD_SYNCHRONIZATION
(ClassName) macro in the constructor
in his CThread
-Derived ClassName class where the thread-task
handler (the virtual ThreadHandler()
method) is actually
implemented. Thread-Handler-Oriented Synchronization is supported for both
Trivial and Notificable CThread
Threads.
CThread
class itself implements an internal synchronization.
This is the special synchronization feature that is not visible from within the
owner thread. Internal synchronization does not impact Lock()
or
Unlock()
mechanism mentioned in the above paragraph under any
circumstances. The benefit of the internal synchronization is a synchronized
access to critical CThread
methods while accessing the one instance
of CThread
object asynchronously.
This kind of synchronization is sometimes called Single Thread Object
Synchronization. If, for example, the childThread is an instance of
CThread
-Derived class, which is shared by two other (arbitrary)
threads parentThread1 and parentThread2, both these parent threads operate on
the childThread object asynchronously. The internal synchronization implemented
in CThread
class guarantees that all critical childThread methods
will be executed properly regardless the parent thread owning the current
childThread focus. The only care that must be taken is that none of the parent
threads deletes the childThread's CThread
object while another is
still operating on it.
Despite the given guaranty there is one situation where the concurrent
operating on the same object may be confusing. It concerns mainly Notificable
Threads and sending commands from the parent threads to the childThread. If both
parent threads send several commands asynchronously to the childThread there is
no any guaranty about which command will be actually handled in the childThread
at a moment. The similar situation may occur also in Trivial Threads while
setting up some important controlling object property (or variable) used in the
childThread by both parent threads concurrently. For this reason, a
concurrency-handling-of-one-object design has to be carefully prepared.
This kind of synchronization is established automatically while registering
CThread
class in an application process for both Trivial and
Notificable Threads.
CThread
-Derived class offers also a global locking mechanism,
which is exclusive for the whole process. The user may use ProcessLock()
or ProcessUnlock()
CThread
static methods (that
were previously opened by OpenProcessLocking()
method) wherever in
a code. These methods are static so there is no necessary to instantiate any
CThread
object. User may use this synchronization mechanism to
accomplish an exclusive access to the global-critical resources (opening the
file, common communication object, singleton etc.). Process Synchronization may
be used in an arbitrary part of the code not necessarily in CThread
tasks only.
The mentioned synchronization does not support an inter-process
synchronization.
Notificable Threads react to the owner-thread incoming commands and allow the
owner to obtain the current thread activity status. Owner thread usually uses
the PostCommand()
method which fires an appropriate command to the thread.
Thread immediately reacts to the incoming command (inside ThreadHandler()
virtual method) and is responsible to handle this command.
Simultaneously, the thread should set the meaningful current activity status by
using SetActivityStatus()
method. Owner thread uses
GetActivityStatus()
method to obtain the current status.
To establish a Notificable thread a developer has to add the
SUPPORT_THREAD_NOTIFICATION
macro in his
CThread
-Derived class constructor where the thread-task handler
(the virtual ThreadHandler()
method) is actually implemented. He
also has to implement the thread-task handler following the specific rules
discussed later. The whole stuff may be arranged automatically by using the
Worker Thread Class Generator Wizard that is discussed in the chapter 2.
The user should always communicate with CThread
notificable
threads via commands. Start(), Pause(), Continue(), Reset(), Stop()
or the general PostCommand() CThread
methods are intended
for such use. Although, this is not the only way how to communicate with
CThread
threads (we may, for example, use methods of a specific
object operating in the thread handler directly), it is highly recommended to
use the mentioned command-communication. The main benefit is a synchronized and
logical access to the thread-task code. Incoming commands fired from everywhere
fill up an internal CThread
command queue and are handled sequentially in the
same order they were fired - first-in-first-out (cyclic stack mechanism). For
example, the calling sequence: Start(), Pause(),
Continue(),
Stop()
fired in one step will be handled exactly in the same order in
which they were called.
CThread
class introduces four helper methods wrapping the
PostCommand()
method: Run(), Pause(), Continue() and
Reset()
. All they do is just firing the corresponding command to a
CThread
thread. These methods just remind the similar functionality
schema provided by schedulers or services. Developers may decide how to
interpret these methods or they may decide not to utilize them at all. What is
important is to handle an appropriate command in the ThreadHandler()
method when a developer decides to use these helpers.
To avoid racing discrepancies between threads, developers should follow
several guidelines while building an application using CThread
threads. An owner thread is responsible for a CThread
thread
lifetime. From the child CThread
thread point of view, thus, the
owner thread exists during the whole thread lifetime. The only responsibility
for such thread is not to destroy the owner thread explicitly.
On the other hand, from the owner-thread point of view, CThread
thread may terminate unpredictably. CThread
object, however,
guarantees that each CThread
method call will be semantically
properly executed regardless the attached Windows thread is alive or not. In
other words, none CThread
method will hang after the thread will
have been prematurely terminated.
The owner thread (or any thread) may utilize some CThread
methods to find out the existence status of the thread (IsAlive(),
GetExitCode(), GetActivityStatus()
etc.). Furthermore, the owner thread
may be notified by some user specific callback that is initiated from within the
CThread
thread to be invoked immediately when some important
situation occurs. Similarly, this thread may set up a useful variable (or an
object property) which is shared by the owner thread as well (in Trivial
Threads).
For CThread
threads cooperating among each other it is a
developer's responsibility how to maintain racing conditions. This usually
strongly depends on the concrete architecture of an application. In general,
avoiding racing problems requires a proper thread-communication design and an
additional developing effort. Developers may also consult some design-patterns
discussing this theme.
There is one big dilemma in a thread theory - "use or not to use" synchronous
methods for controlling of threads. An advantage of such schema is a guaranty
that each method sending a command to a child thread invoked from the owner
thread waits until the child thread actually completes the command. If, for
example, the thread is forced to be paused by some, for example,
PauseThread()
method called from the owner thread,
PauseThread()
will wait until the thread is actually paused. This
works fine for many worker threads that are more or less independent from their
owner threads. Usually, SetEvent-WaitForSingleObject programming model is used
in this schema.
Unfortunately, there are many cases when this schema is inapplicable. In GUI
applications requiring bi-directional communication between an application and a
thread this model is a priori inappropriate. Following the previous example, if
a GUI application calls the PauseThread()
method it may wait a long
time for the thread completion which leads to a message queue blocking. In this
situation the application hangs until the method is completed. Moreover, if for
any reason the PauseThread()
method hangs or fails the application
may hang forever.
Even worse situation occurs when the thread tries to cooperate with the main
GUI application using the PostMessage()
and SendMessage()
functions. If PauseThread()
is invoked in the application
and the thread sends consequently some message back to the application waiting
for a response, this message cannot be handled in the application. The message
is namely to be handled by the application thread but the application thread is
blocked by the PauseThread()
method. This is a serious situation
leading to an excellent deadlock. The only safe using of a synchronous
thread-controlling method in a GUI application is the case when the thread does
not require any task to be executed by the application thread while completing
the appropriate command.
CThread
class uses synchronous methods as few as possible. There
are just four methods that works synchronously: Start()
and
Kill()
methods that are, fortunately, not dangerous because of
their principal independence from the owner thread, and Stop() and
WaitForActivityStatus()
methods for which a special care has to be
taken. For more information concerning these methods refer to
CThread
Reference Manual (CThread.hlp or CThread.htm).
Instead of distinguishing among many possible scenarios how to manage
synchronous calls, CThread
class provides only one general method
for such purposes: WaitForActivityStatus()
. This method is called
from the owner thread and just waits until the thread sets up a desired thread
activity status. The method, however, requires a proper synchronous-call design
varying from case to case (see CThread
Reference Manual).
Stopping CThread
threads is discussed in details in the next
paragraph.
CThread
object wraps a Windows worker thread. Nevertheless, the
thread may be used in GUI context as well. As a worker thread
CThread
object does not contain its own message queue and therefore
shares the same queue as the main application thread. Thread itself communicates
with this queue (or a Windows window procedure directly) usually via the
PostMessage()
and SendMessage()
functions or methods
utilizing these functions implicitly. Using thePostMessage()
function is generally considered as more safe.
Sending messages from the CThread
thread to the main application
message queue is preferred by using the Windows function PostMessage(hWnd,
nMsg, lParam, wParam)
requiring the original Windows HWND handle of the
main application window. Generally, there is no guaranty about lifetime of C++
objects originating in a different thread. These C++ objects have to be handled
carefully in the CThread
context.
Normally, there is not big problem while communicating with the message queue
belonging to the main application window (if no synchronous thread-controlling
methods are called from the main thread - see the previous paragraph).
CThread
thread posts messages to the main window in the same way as
other objects do in the main application. Posted message is added at the end of
the queue and sequentially handled. However, there is one important exception -
stopping the thread. Stopping the CThread
thread is accomplished by
the CThread's Stop()
method called from the main application
thread. Stop()
method is primarily a synchronous method and should
wait until the CThread
thread actually finishes. If the
CThread
thread is forced to stop from within the application but is
still communicating with the application thread or the message queue (and
eventually waiting for message completion - some methods like the List Control's
DeleteAllItems()
use implicit SendMessage()
notification), that thread may not be properly terminated. The thread waits for
the message completion that is to be done in the main application thread but the
application thread itself is blocked by the Stop()
method in some
message handler. This leads to a deadlock and the application freezes.
To get out of such difficulties we have to use one 'tricky' method. Suppose
we are using the CThread
thread communication with the application
message queue (or, generally, with the application thread, e.g. through
SendMessage()
). First of all, a developer has to define a special
activity status, for example, THREAD_PREPARED_TO_TERMINE
in his
CThread
-Derived class. This activity status describes the situation
that the CThread
thread having set up this activity status will not
utilize neither the application message queue nor the application thread any
more, thus, from this moment the thread will neither post nor send any Windows
message to the application. The fragment of code setting up this activity status
in the CThread's ThreadHandler()
method is as follows:
...
case CThread::CMD_RUN:
SetActivityStatus(CThread::THREAD_RUNNING);
PostOrSendMessagesToTheApplication();
break;
...
case CThread::CMD_STOP:
CompleteCommunicationFinally();
SetActivityStatus(CThreadDerived::THREAD_PREPARED_TO_TERMINE);
bContinue = FALSE;
break;
....
The next step is to stop the CThread
thread from within the main
application (owner thread). The best way is to use the main frame's
OnClose()
method in main-frame applications (in dialog-based
applications the situation is described as well). The main idea is to suppress
closing the main frame window until the CThread
thread's activity
status is equal to THREAD_PREPARED_TO_TERMINE
. This is accomplished
by periodical firing the WM_CLOSE
message from within the
OnClose()
method to prevent an application-thread-blocking and
allowing the CThread
thread to complete its eventual message
handling. The whole mentioned stuff is accomplished in the following code in the
main application:
For main-frame-based applications (SDI, MDI):
CMainFrame::OnClose()
{
DWORD dwExitCode;
m_myThread.Stop(dwExitCode, 0);
if (m_myThread.GetActivityStatus() !=
CThreadDerived::THREAD_PREPARED_TO_TERMINE)
{
PostMessage(WM_CLOSE);
}
else
{
m_myThread.Stop(dwExitCode);
CFrameWnd::OnClose();
};
}
Analogically for dialog-based applications (we will use OnCancel() virtual
method here - this method is not a message handler!):
CMyDialog::OnCancel()
{
DWORD dwExitCode;
m_myThread.Stop(dwExitCode, 0);
if (m_myThread.GetActivityStatus() != CThreadDerived::THREAD_MSG_SESSION_CLOSED)
{
PostMessage(WM_COMMAND, MAKEWPARAM((WORD)IDCANCEL, (WORD)IDCANCEL));
}
else
{
m_myThread.Stop(dwExitCode);
CDialog::OnCancel();
};
}
In some specific cases more complex handling is needed. Developers may want
to use the special flag indicating the end of message handling initiated in the
CThread
thread. They may also want to stop the thread in some other
non-finalize method. But the basic idea not to block the application thread and
periodically call the stop-thread-handler by the PostMessage()
method sketched in the above code remains the same.
CThread
-Derived classes can be generated automatically by using
the Worker Thread Class Generator Wizard enclosed in this delivery. A user may
choose the base CThread
derived class from which he wants to derive
his own Trivial or Notificable CThread
-Derived class and implements
the thread specific task by writing down the code in the ThreadHandler()
method skeleton. He may also establish some kind of synchronization or
share the synchronization already established in the selected base class. The
Worker Thread Class Generator workaround does not require any special
explanation and it's intuitive at first glance.
After generating the CThread
-Derived class source the developer
has to implement the thread handler at least in one such class (from the
class-object-hierarchy point of view). The thread handler is declared and
implemented in the *.h and *.cpp files as a virtual
method:CThreadDerived::ThreadHandler().
According to the article 1 the user may implement one of the two possible
paradigms.
1. Trivial Thread: Simple sequence of commands. ThreadHandler()
in this case may look as follows:
DWORD CThreadDerived::ThreadHandler()
{
BOOL bEverythingOK;
<command_1>;
<command_2>;
<command_3>;
...
<command_n>;
...
if (bEverythingOK)
return CThread::DW_OK ;
else
return CThread::DW_ERROR;
}
2. Notificable Thread: ThreadHandler()
implements the task which
is sensitive to the owner thread incoming commands. The owner thread may, in
turn, obtain the current thread activity status in an arbitrary phase of running
thread. Thread Handler() in such case should look somehow like this:
DWORD CThreadDerived::ThreadHandler()
{
BOOL bContinue = TRUE;
int nIncomingCommand;
do
{
WaitForNotification(nIncomingCommand, CThreadDerived::DEFAULT_TIMEOUT);
switch (nIncomingCommand)
{
case CThread::CMD_TIMEOUT_ELAPSED:
if (GetActivityStatus() != CThread::THREAD_PAUSED)
{
UserSpecificTimeoutElapsedHandler();
HandleCommandImmediately(CMD_RUN);
}
break;
case CThread::CMD_INITIALIZE:
UserSpecificOnInitializeHandler();
HandleCommandImmediately(CMD_RUN);
break;
case CThread::CMD_RUN:
if (GetActivityStatus() != CThread::THREAD_PAUSED)
{
SetActivityStatus(CThread::THREAD_RUNNING);
UserSpecificOnRunHandler();
Lock();
UserSpecificCriticalCode();
Unlock();
}
break;
case CThread::CMD_PAUSE:
if (GetActivityStatus() != CThread::THREAD_PAUSED)
{
UserSpecificOnPauseHandler();
SetActivityStatus(CThread::THREAD_PAUSED);
}
break;
case CThread::CMD_CONTINUE:
if (GetActivityStatus() == CThread::THREAD_PAUSED)
{
SetActivityStatus(CThread::THREAD_CONTINUING);
UserSpecificOnContinueHandler();
HandleCommandImmediately(CMD_RUN);
}
break;
case CThreadDerived::CMD_USER_SPECIFIC:
UserSpecificOnUserCommandHandler();
break;
case CThread::CMD_STOP:
UserSpecificOnStopHandler();
bContinue = FALSE;
break;
default:
break;
};
} while (bContinue);
return (DWORD)CThread::DW_OK;
}
Establishing (and starting) thread objects of the CThreadDerived
class in the owner thread as well as handling these threads may look as
in the following example:
CMainProgram::HandleThreads();
{
CThreadDerived thread1, thread2;
try
{
thread1.Start();
thread2.Start();
...
thread1.Pause();
...
thread2.Continue();
thread2.PostCommand(CThreadDerived::CMD_USER_SPECIFIC);
...
thread1.Stop();
thread2.Stop();
}
catch (CThreadException* pe)
{
pe->ReportError();
pe->Delete();
};
}
Note 1:
The communication from the owner thread to the Notificable Thread should
always be established by sending the commands that are recognizable in the
ThreadHandler()
method.
Note 2:
Phrases using italic font in the mentioned source code list mean
CThreadDerived
specific methods or data members. All others are
Windows System functions or CThread
provided methods and data
members.
More detailed information concerning CThread
class can be found
in CThread
Reference Manual (CThread.hlp, CThread.htm and
CThread.doc files) in '/Doc' subdirectory of the main installation
directory.
Author: Dominik Filipp, � 1999, Bratislava, Slovakia, Europe
E-mail
address: Dominik.Filipp@work4.sk
To display a list of topics by category, click any of the contents entries
below. To display an alphabetical list of topics, choose the Index button.
C/C++ Elements
Classes and Class Members
Structures and Enums
Other
Overviews
Modules
Help file built: 08/30/99
About Autoduck
The sources for this Help file were generated by Autoduck, the source code
documentation tool that generates Print or Help files from tagged comments in C,
C++, Assembly, and Basic source files.
For more information, contact Eric Artzt (erica@microsoft.com).
CThread
Class
The base MFC CObject-derived class that encapsulates WINDOWS Worker
Thread abilities.
CThread
class offers many features that are
not implemented or supported by WINDOWS System. It allows to build up the
full-fledged OOP Class hierarchy, supports several levels of safe Thread
Synchronization as well as the Thread Notification.
Detailed information
how do CThreads work, how should be managed or handled can be found in the
'Developer.doc' documentation in '\\Doc' subdirectory of the main installation
directory.
CThreadException Class
The base
CException
-derived class used in
CThread
-Derived
classes.
License Conditions
This software is a freeware and may be freely used or distributed without
restriction.
CThread.cpp
Description
PROJECT : CThread
Class
SUBSYSTEM : CThread
Base Class
AUTHOR : Dominik Filipp, � 1999, Slovakia, Europe
DESCRIPTION:
Abstract Base CThread
Class implementation
file.
CThread.h
Description
PROJECT : CThread
Class
SUBSYSTEM : CThread
Base Class
AUTHOR : Dominik Filipp, � 1999, Slovakia, Europe
DESCRIPTION:
Abstract Base CThread
Class header
file.
CThread
class
CThread
class CThread: public CObject
CThread
Class Members
Class Members
Public Members:
- CThread(void* pOwnerObject = NULL, LPARAM
lParam = 0L)
CThread
Constructor
- virtual
~CThread()
CThread
Destructor
- SECURITY_ATTRIBUTES
GetAttributes() const
- Get Thread Attributes
- DWORD
GetStackSize() const
- Get Thread Stack Size
- HANDLE
GetHandle() const
- Get Thread Handle
- DWORD
GetID() const
- Get Thread ID
- DWORD
GetExitCode() const
- Get Thread Exit Code
- int
GetActivityStatus()
const
- Get Thread Activity Status
- int
GetPriority() const
- Get WINDOWS Thread Priority
- BOOL
IsAlive()
- Check if Thread is Alive
- void
Start()
- Start Thread
- void
Run()
- Fire Run Command
- void
Pause()
- Fire Pause Command
- void
Continue()
- Fire Continue Command
- void
Reset()
- Fire Reset Command
- BOOL
Stop(DWORD& dwExitCode, DWORD
dwTimeout = CThread::DW_INFINITE)
- Fire Stop Command
- void
Kill(DWORD dwExitCode =
CThread::DW_OK, BOOL bCloseAnyway = FALSE)
- Kill Thread
- void
PostCommand(int
nCommand)
- Post Command to Thread
- void
ResetCommands()
- Cancel All Notification Commands
- void
SetOwnerParams(void*
pOwnerObject, LPARAM lParam = 0L)
- Set Owner Object Parameters
- void
GetOwnerParams(void*&
pOwnerObject, LPARAM& lParam) const
- Get Owner Object Parameters
- void
SetAttributes(LPSECURITY_ATTRIBUTES
lpThreadAttributes = NULL)
- Set Thread Attributes
- void
SetStackSize(DWORD
dwStackSize = 0)
- Set Thread Stack Size
- BOOL
SetPriority(int nPriority =
THREAD_PRIORITY_NORMAL)
- Set WINDOWS Thread Priority
- BOOL
WaitForActivityStatus(int
nActivityStatus, DWORD dwTimeout = CThread::DW_INFINITE) const
- Wait For the Desired
CThread
Activity Status
- static void
OpenProcessLocking()
- Open Process Synchronization
- static void
CloseProcessLocking()
- Close Process Synchronization
- static void
ProcessLock()
- Lock Critical Code in Process Synchronization Mode
- static void
ProcessUnlock()
- Unlock Critical Code in Process Synchronization Mode
Class Members
Protected Members:
- void
SetActivityStatus(int
nActivityStatus)
Set Thread Activity Status
void Lock()
Lock Critical Code in Thread-Handler-Oriented Synchronization Mode
void Unlock()
Unlock Critical Code in Thread-Handler-Oriented Synchronization Mode
void WaitForNotification(int&
nIncomingCommand, DWORD dwDefaultTimeout = CThread::DW_INFINITE)
Wait for Incoming Commands
BOOL HandleCommandImmediately(int
nCommand)
Handle Command Immediately Bypassing Other Pending Commands
virtual DWORD ThreadHandler()
Main Thread Task Handler (Abstract Declaration)
virtual void OnKill()
Make Specific Unallocations After The Thread Has Been Killed
CThread::CloseProcessLocking
static void CThread::CloseProcessLocking(void)
Static method that closes the process synchronization that was previously
opened by OpenProcessLocking. The synchronization itself is
accomplished by calling ProcessLock and ProcessUnlock methods
between which is the critical code that is to be executed process-exclusively.
As a static method may be used wherever in the code without constructing
any CThread
object.
See Also
OpenProcessLocking
ProcessLock
ProcessUnlock
Back to CThread
CThread::Continue
void CThread::Continue(void)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Fires CThread::CMD_CONTINUE
Command and notifies CThread
object. Used in
the owner thread. This method is valid only if CThread
-Derived
class supports Thread Notification and CThread
thread has been
successfully started. Otherwise it has no any effect.
To use the method
properly the ThreadHandler method must be able to handle CThread::CMD_CONTINUE
Command as well as implement the specific task
corresponding to this command. This method returns immediately after the
command has been fired. The owner thread may, however, wait for completion of
the corresponding task by using the paradigm described in the
WaitForActivityStatus method.
This method is a helper method
simplifying the semantic control of Notificable CThread
threads acting in a
'scheduler' or 'service' - like manner. It's up to the developer's
responsibility how to interpret and implement (or refuse at all) this method.
For more information see 'Developer.doc' documentation.
See Also
PostCommand
WaitForActivityStatus
CThread
Predefined Commands
Back to CThread
CThread::CThread
CThread::CThread(void* pOwnerObject = NULL, LPARAM
lParam = 0 )
CThread
constructor. User may pass a so-called 'Owner object' to
the CThread
class. The Owner object is an arbitrary object claimed
to be an owner of CThread
object. In such way the Owner object may
be notified by CThread
object while running the thread. Optional
LPARAM
parameter allows the user to pass an additional useful information. It's
up to the developer's responsibility how to interpret and implement the Owner
object parameters in CThread
-Derived class. CThread
class itself just stores the passed values. The mentioned parameters may
be also set up or read after CThread
object construction by calling
the SetOwnerParams and GetOwnerParams methods.
While
constructing CThread
object no any WINDOWS thread is being
started.
Parameters
- pOwnerObject
[in] CThread
Owner object.
lParam
[in] General parameter passed to CThread
object.
See Also
SetOwnerParams
GetOwnerParams
Back to CThread
CThread::GetActivityStatus
int CThread::GetActivityStatus(void)
Gets the current CThread
activity status. This method is
normally called from within the owner thread to obtain the current activity of
the owned thread. CThread
class offers the predefined values as
seen in the 'Return Value' section.
Return Value
Current CThread
activity status.
- CThread::THREAD_CREATED
- Thread was successfully created (activity status set by the Start() method).
- CThread::THREAD_STOPPED
- Thread is stopped.
- CThread::THREAD_RUNNING
- Thread is running.
- CThread::THREAD_PAUSED
- Thread is paused.
- CThread::THREAD_CONTINUING
- Thread is continuing.
- CThread::THREAD_PENDING
- Thread is pending.
- CThread::THREAD_USER_ACTIVITY
- Base offset for user-defined activity statuses.
See Also
SetActivityStatus
Back to CThread
CThread::GetAttributes
SECURITY_ATTRIBUTES CThread::GetAttributes(void)
Gets the WINDOWS thread security attributes (see WINDOWS Threads in Microsoft
MSDN documentation).
Return Value
Fills up the SECURITY_ATTRIBUTES
structure with valid data. If the WINDOWS
thread is not created the SECURITY_ATTRIBUTES
structure is null-reset.
See Also
SetAttributes
Back to CThread
CThread::GetExitCode
DWORD CThread::GetExitCode(void)
Gets CThread
thread exit code - a value that is returned by
ThreadHandler method - or, generally, it's a return value of the thread
controlling function. GetExitCode()
method returns the valid exit code
regardless the WINDOWS thread is alive or not.
Return Value
CThread
thread exit code.
Back to CThread
CThread::GetHandle
HANDLE CThread::GetHandle(void)
Gets the WINDOWS thread handle (see WINDOWS Threads in Microsoft MSDN
documentation).
Return Value
Handle of WINDOWS thread or NULL if the thread is not created.
Back to CThread
CThread::GetID
DWORD CThread::GetID(void)
Gets the WINDOWS thread ID (see WINDOWS Threads in Microsoft MSDN
documentation).
Return Value
WINDOWS thread ID or 0 if the thread is not created.
Back to CThread
CThread::GetOwnerParams
void CThread::GetOwnerParams(void*&
pOwnerObject, LPARAM& lParam)
Retrieves the CThread
Owner object parameters.
Parameters
- pOwnerObject
[out] Reference to the CThread
Owner object being retrieved.
lParam
[out] Reference to the LPARAM parameter being retrieved.
See Also
SetOwnerParams
Back to CThread
CThread::GetPriority
int CThread::GetPriority(void)
This method gets the WINDOWS thread priority.
GetPriority()
just
encapsulates the WINDOWS GetThreadPriority()
function. For more information see
Win32 SDK Programmer's Reference.
Return Value
Current WINDOWS thread priority or THREAD_PRIORITY_ERROR_RETURN
if an error
occurs. Can be one of the following:
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_IDLE
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_TIME_CRITICAL
See Also
SetPriority
Back to CThread
CThread::GetStackSize
DWORD CThread::GetStackSize(void)
Gets the WINDOWS thread stack size (see WINDOWS Threads).
Return Value
WINDOWS thread stack size.
See Also
SetStackSize
Back to CThread
CThread::HandleCommandImmediately
void CThread::HandleCommandImmediately(int nCommand)
This helper method is used for immediate sending of CThread
commands fired from within the ThreadHandler method in the actual
Notificable CThread
thread.
In Notificable CThread
threads the ThreadHandler method contains the 'case' switch in
which incoming commands are handled. In some cases the resolved and executed
command has to immediately invoke (and handle) another internal command in this
'case' switch to properly complete its task. Users should not use the
PostCommand oriented methods in such case because the command queue may
not be empty. This queue may be namely filled up by another thread and, thus, an
additional internal completion command will be just posted at the end of the
queue. In consequence, the next handled command will be the first pending in the
queue and not that one intended to be handled immediately.
For this reason a
special command-handling mechanism is desired and is supported by this method.
Requested internal command to be handled immediately is stored in the standard
CThread
command queue as the first pending command bypassing all
already stored commands. Restoring of internal commands is accomplished by the
same method as other standard commands, by the WaitForNotification
method. The difference is that an internal command is handled always as the
first command.
As an example we may consider the starting of a
notificable CThread
thread. After starting the thread the
CMD_INITIALIZE
command is fired as the first command. This command is handled in
the corresponding 'case' branch in the ThreadHandler method, in which the
basic initialization is accomplished. As the next logical step after the
initialization is to get run the main thread task immediately. Thus, before
leaving the initialization 'case' branch the HandleCommandImmediately(CMD_RUN)
method is called. CMD_RUN
command fired in such manner bypasses all pending
commands and is returned (via the WaitForNotification method) back to the
'case' switch as the following command. All pending commands will be resolved
afterwards.
The term 'internal commands' means just another kind of
firing and handling of standard commands. Users use the same commands (more
precisely, command IDs) as in the PostCommand method.
This method
is valid only if CThread
-Derived class supports Thread Notification
and the CThread
thread has been successfully started. Otherwise it
has no any effect.
Important note:
This method should
be called only in the CThread
thread (in the ThreadHandler
method).
Return Value
TRUE if the command was inserted in the command queue.
Parameters
- nCommand
[in] Desired command to be handled immediately.
See Also
ThreadHandler
PostCommand
WaitForNotification
Back to CThread
CThread::IsAlive
BOOL CThread::IsAlive(void)
Checks if the current CThread
thread is still alive.
Return Value
TRUE if the thread is alive otherwise FALSE.
Back to CThread
CThread::Kill
void CThread::Kill(DWORD dwExitCode =
CThread::DW_OK, BOOL bCloseAnyway = FALSE )
throws CThreadException of type:
CThreadException::CANNOT_TERMINATE_THREAD
This method kills the
WINDOWS thread connected to CThread
object. Used in the owner
thread. The method returns after the WINDOWS thread has been actually killed, or
some significant error occurs. CThread
threads should always
terminate either by leaving the thread-controlling function attached to the
WINDOWS thread or by calling Stop method in notificable threads. Killing threads is the last-chance stopping mechanism and should be used in
emergency cases only. While killing the thread by using this method the
OnKill virtual method is invoked to provide the last chance for making
necessary unallocations specific to the thread being killed.
For more
information see 'Terminating WINDOWS Threads' in Microsoft MSDN
documentation.
Parameters
- dwExitCode
[in] Suggested WINDOWS thread exit code. (see 'TerminateThread()' WINDOWS
function in Microsoft MSDN documentation).
bCloseAnyway
[in] Closes the CThread-thread regardless the thread has been destroyed or
not. By using this parameter the CThread-thread is correctly closed and
unregistered even if the corresponding WINDOWS thread cannot be properly
terminated. Users should call this method again (using 'bCloseAnyway = TRUE') if
it's not possible to recover the termination failure - best way is to call it in
the 'catch' clause for an exception thrown by this method. By enabling this
parameter no any CThreadException
exception is thrown.
See Also
OnKill
Stop
Back to CThread
CThread::Lock
void CThread::Lock(void)
Marks the beginning of the critical code to be 'Thread-Handler-Oriented'
synchronized. This special synchronization mechanism allows to lock the critical
code and make it exclusive for the first thread reaching this method.
Consequently all other CThread
objects that operate on the same
ThreadHandler are blocked until the thread unlocks the critical code.
Other threads operating on the different ThreadHandler are not blocked
and are synchronized in exactly same way in their own group. Thus, CThreads
objects can be splitted into the groups operating on the same
ThreadHandler method. Each group is synchronized independently to each
other.
All managing concerning this kind of synchronization is done
automatically, users do not care about any aspect of synchronization. All they
have to do is to use the Lock() and Unlock methods to bound the critical
code. Thread-Handler-Oriented synchronization is, however, not always
usable. If the user needs to lock the shared common object that cannot be
accessed simultaneously under any circumstances, he should use
ProcessLock and ProcessUnlock methods. These methods guarantee the
process-exclusive access to the critical code (but not an inter-process
exclusive access). Lock()
method must be followed by Unlock method in
a way to prevent eventual deadlocks.
This kind of synchronization can be
established by adding SUPPORT_THREAD_SYNCHRONIZATION(ClassName) macro to
the user CThread
-Derived class constructor in which
ThreadHandler method is implemented.
Important note:
Both Lock()
and Unlock()
methods may be called from within the
appropriate CThread
thread only (represented by the ThreadHandler()
method
body). The methods should not be published and cannot be delegated to other
threads - otherwise unpredictable deadlocks may arise.
See Also
Unlock
ProcessLock
ProcessUnlock
Back to CThread
CThread::OnKill
void CThread::OnKill(void)
Virtual method that is invoked while the Kill method is being
executed. OnKill()
is called after the WINDOWS thread has been actually
destroyed. Users may unallocate all extra resources that were needed in the
CThread
-Derived instance object. Default version does nothing
users may, however, implement this method in their CThread
-Derived
class.
All extra resources should be referenced through
CThread
-Derived class member data, because in the moment of
OnKill()
execution all local variables in the ThreadHandler method are
not more valid - thread is already destroyed and its controlling function is
detached. OnKill()
virtual method doesn't have to call the base
CThread::OnKill()
method.
Note 1: Users should unallocate (detach,
close...) resources that rely only to the current instance of
CThread
-Derived object that is being killed. Keep in mind that in
some cases the same resources may be used by other running instances as well. In
this situation the user is responsible to clean up such shared resources.
Note 2: OnKill() method doesn't have to be invoked under any
circumstances. If the thread regularly finished before the Kill method
has been called the Kill method does nothing, thus, OnKill() method is
not invoked. OnKill() is normally used as a last chance emergency clean-up.
See Also
Kill
ThreadHandler
Back to CThread
CThread::OpenProcessLocking
static void CThread::OpenProcessLocking(void)
Static method that opens the process synchronization. After the first call
the process synchronization is opened. Additional call of this method has no any
effect - the synchronization remains opened. The synchronization itself is
accomplished by calling ProcessLock and ProcessUnlock methods
between which is the critical code that is to be executed process-exclusively.
Opened process-synchronization should be finally closed by
CloseProcessLocking method. This locking mechanism does not support
an inter-process synchronization.
As a static method may be used
wherever in the code without constructing any CThread
object.
See Also
CloseProcessLocking
ProcessLock
ProcessUnlock
Back to CThread
CThread::Pause
void CThread::Pause(void)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Fires
CThread::CMD_PAUSE
Command and notifies CThread
object. Used in the
owner thread. This method is valid only if CThread
-Derived class
supports Thread Notification and CThread
thread has been
successfully started. Otherwise it has no any effect. To use the method
properly the ThreadHandler method must be able to handle
CThread::CMD_PAUSE
Command as well as implement the specific task corresponding
to this command.
This method returns immediately after the command has been
fired. The owner thread may, however, wait for completion of the corresponding
task by using the paradigm described in the WaitForActivityStatus method.
This method is a helper method simplifying the semantic control of
Notificable CThread
threads acting in a 'scheduler' or 'service' - like manner.
It's up to the developer's responsibility how to interpret and implement (or
refuse at all) this method.
For more information see 'Developer.doc'
documentation.
See Also
PostCommand
WaitForActivityStatus
CThread
Predefined Commands
Back to CThread
CThread::PostCommand
void CThread::PostCommand(int nCommand)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
PostCommand()
method is the base method with which the owner thread may manage notificable
CThread
objects. By calling PostCommand() the owner thread fires
desired commands to the thread belonging to CThread
object. The
thread consequently receives a signal to leave WaitForNotification method
which is used in the ThreadHandler method (implemented in
CThread
-Derived class) and restores the command fired from the
owner thread. Obtained command is immediately executed in the thread body.
Developer is responsible to handle the fired command in the ThreadHandler
method. PostCommand() mechanism is the recommended way how to manage
CThread
objects. It's also the base concept for other
command-oriented methods like Start(), Pause(), Continue(), Reset() or Stop()
.
Each of these methods sets the appropriate command and sends a signal to the
thread which handles the command. Using this paradigm the thread notifications
coming from outside keep the synchronization features provided by CThread
class.
PostCommand()
method supports so-called 'stackable commands'
which allows the thread-owner process to pump all desired commands at one step.
All such commands will be resolved in the thread task body in exactly the same
order as they were pumped in the owner thread (cyclic stack mechanism). User may
define an arbitrary count of user-specific commands. For this purpose the CThread
class offers the start offset command ID: CThread::CMD_USER_COMMAND. All
command IDs below this value is reserved by CThread
class and
should not be used. In this case the user is responsible to handle the
user-specific command in the ThreadHandler method in the
CThread
-Derived class.
This method is valid only if
CThread
-Derived class supports Thread Notification. Thread
Notification may be established by adding SUPPORT_THREAD_NOTIFICATION
macro in
the CThread
-Derived class constructor in which ThreadHandler
method is actually implemented. Otherwise PostCommand()
method has no any
effect. This method is usable after the CThread
thread has been
successfully started.
PostCommand()
returns immediately after the
command has been actually fired. The owner thread may, however, wait for
completion of the task corresponding to the fired command (implemented in the
ThreadHandler method) by using the paradigm described in the
WaitForActivityStatus method.
Detailed information how to use
this method as well as how to manage fired commands in the thread task body can
be found in the 'Developer.doc' documentation.
Parameters
- nCommand
[in] Desired command fired from within the owner thread that is to be
executed in CThread
task body - ThreadHandler.
See Also
WaitForNotification
WaitForActivityStatus
HandleCommandImmediately
CThread
Predefined Commands
Back to CThread
CThread::ProcessLock
static void CThread::ProcessLock(void)
Static method that marks the beginning of the critical code that is to be
executed process-exclusively. ProcessUnlock method is the counterpart
of the ProcessLock()
method which bounds the end of the critical code. Both
methods should be used in a way to prevent eventual deadlocks. Before using the
method the process-synchronization must be opened by OpenProcessLocking
method. This locking mechanism does not support an inter-process
synchronization.
As a static method may be used wherever in the code
without constructing any CThread
object.
See Also
OpenProcessLocking
CloseProcessLocking
ProcessUnlock
Back to CThread
CThread::ProcessUnlock
static void CThread::ProcessUnlock(void)
Static method that marks the end of the critical code that is to be executed
process-exclusively. ProcessLock method is the counterpart of
ProcessUnlock()
method which bounds the start of the critical code. Both methods
should be used in a way to prevent eventual deadlocks. Before using the method
the process-synchronization must be opened by OpenProcessLocking method.
This locking mechanism does not support an inter-process synchronization.
As a static method may be used wherever in the code without constructing
any CThread
object.
See Also
OpenProcessLocking
CloseProcessLocking
ProcessLock
Back to CThread
CThread::Reset
void CThread::Reset(void)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Fires
CThread::CMD_RESET
Command and notifies CThread
object. Used in the
owner thread. This method is valid only if CThread
-Derived class
supports Thread Notification and CThread
thread has been
successfully started. Otherwise it has no any effect. To use the method
properly the ThreadHandler method must be able to handle
CThread::CMD_RESET
Command as well as implement the specific task corresponding
to this command. This method returns immediately after the command has been
fired. The owner thread may, however, wait for completion of the corresponding
task by using the paradigm described in the WaitForActivityStatus method.
This method is a helper method simplifying the semantic control of
Notificable CThread
threads acting in a 'scheduler' or 'service' - like manner.
It's up to the developer's responsibility how to interpret and implement (or
refuse at all) this method.
For more information see 'Developer.doc'
documentation.
See Also
PostCommand
WaitForActivityStatus
CThread
Predefined Commands
Back to CThread
CThread::ResetCommands
void CThread::ResetCommands(void)
Cancels all thread-notification commands fired by the PostCommand
method and waiting in the queue to be processed. This method is useful when
the last important command is intended to be sent to the CThread
object. To ensure that no any other command is to be processed, the owner
thread may cancel all such commands pending in the CThread
command
queue.
See Also
PostCommand
WaitForNotification
Back to CThread
CThread::Run
void CThread::Run(void)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Fires
CThread::CMD_RUN
Command and notifies CThread
object. Used in the
owner thread. This method is valid only if CThread
-Derived class
supports Thread Notification and CThread
thread has been successfully started.
Otherwise it has no any effect. To use the method properly the
ThreadHandler method must be able to handle CThread::CMD_RUN
Command as
well as implement the specific task corresponding to this command.
This
method returns immediately after the command has been fired. The owner thread
may, however, wait for completion of the corresponding task by using the
paradigm described in the WaitForActivityStatus method.
This
method is a helper method simplifying the semantic control of Notificable
CThread
threads acting in a 'scheduler' or 'service' - like manner. It's up to
the developer's responsibility how to interpret and implement (or refuse at all)
this method.
For more information see 'Developer.doc' documentation.
See Also
PostCommand
WaitForActivityStatus
CThread
Predefined Commands
Back to CThread
CThread::SetActivityStatus
void CThread::SetActivityStatus(int nActivityStatus)
Sets CThread
activity status. CThread
activity
status describes the current CThread
activity. This method should be
meaningfully used in the ThreadHandler CThread
-Derived class
method. to inform the owner thread about the current CThread
object
activity. Owner thread may call GetActivityStatus method to restore the
current status. CThread
class offers the predefined values as
seen in the 'Parameters' section.
For more information how to use this
method see 'Developer.doc' documentation.
Parameters
- nActivityStatus
[in] CThread
activity status.
CThread::THREAD_CREATED
Thread was successfully created (activity status set by the Start() method).
CThread::THREAD_STOPPED
Thread is stopped.
CThread::THREAD_RUNNING
Thread is running.
CThread::THREAD_PAUSED
Thread is paused.
CThread::THREAD_CONTINUING
Thread is continuing.
CThread::THREAD_PENDING
Thread is pending.
CThread::THREAD_USER_ACTIVITY
Base offset for user-defined activity statuses.
See Also
GetActivityStatus
Back to CThread
CThread::SetAttributes
void
CThread::SetAttributes(LPSECURITY_ATTRIBUTES
lpThreadAttributes = NULL)
Sets the WINDOWS thread security attributes (see WINDOWS Threads in Microsoft
MSDN documentation).
Thread attributes - if necessary - should be set before
CThread
thread is started.
Parameters
- lpThreadAttributes
[in] Pointer to the security attributes structure.
SECURITY_ATTRIBUTES
structure may be created temporarily. Passing its
pointer to this method means copying the structure contents to the internal data
space of CThread
object. Therefore, thread attributes remain valid
regardless the SECURITY_ATTRIBUTES
structure (which 'lpThreadAttributes'
parameter points to) exists or not.
See Also
GetAttributes
Back to CThread
CThread::SetOwnerParams
void
CThread::SetOwnerParams(void* pOwnerObject,
LPARAM lParam = 0)
Sets CThread
Owner object parameters. User may pass a so-called
'Owner object' to the CThread
class. The Owner object is an
arbitrary object claimed to be an owner of CThread object. In such way the Owner
object may be notified by CThread
object while running the thread.
Optional LPARAM parameter allows the user to pass an additional useful
information. It's up to the developer's responsibility how to interpret and
implement the Owner object parameters in CThread
-Derived class.
CThread
class itself just stores the passed values. The mentioned
parameters can be read after the CThread
object construction by
calling the GetOwnerParams method.
Parameters
- pOwnerObject
[in] CThread
Owner object.
lParam
[in] General parameter passed to CThread
object.
See Also
GetOwnerParams
Back to CThread
CThread::SetPriority
DWORD CThread::SetPriority(int nPriority =
THREAD_PRIORITY_NORMAL)
This method sets the WINDOWS thread priority. The priority may be set after
the WINDOWS thread has been started.
SetPriority()
just encapsulates the
WINDOWS SetThreadPriority()
function. For more information see Win32 SDK
Programmer's Reference.
Return Value
TRUE - the priority was properly set.
FALSE - the priority was not set or
the thread is not running.
Parameters
- nPriority
[in] WINDOWS thread priority. Can be one of the following:
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_IDLE
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_TIME_CRITICAL
See Also
GetPriority
Back to CThread
CThread::SetStackSize
void CThread::SetStackSize(DWORD dwStackSize = 0)
Sets the WINDOWS thread stack size (see WINDOWS Threads in Microsoft MSDN
documentation).
Thread stack size - if necessary - should be set before
CThread
thread is started.
Parameters
- dwStackSize
[in] Desired WINDOWS thread stack size.
See Also
GetStackSize
Back to CThread
CThread::Start
void CThread::Start(void)
throws CThreadException of types:
CThreadException::CANNOT_CREATE_THREAD,
CThreadException::THREAD_ALREADY_STARTED,
CThreadException::CANNOT_CREATE_NOTIFICATION_OBJECT,
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
This method
starts the WINDOWS thread connected to CThread
object. Used in the
owner thread. Once established the WINDOWS thread cannot be started again until
it terminates. Before starting a thread user may set up WINDOWS thread
attributes or thread stack size if necessary. This can be accomplished by
calling the SetAttributes or SetStackSize methods. In
notificable threads Start()
method fires CThread::CMD_INITIALIZE
Command
immediately after the WINDOWS thread was being established.
CThread::CMD_INITIALIZE
Command must be handled in the ThreadHandler
method.
This method is a synchronous method. It returns only if the
WINDOWS thread has been successfully started or some significant error occurs.
In this case the method returns immediately by throwing the appropriate
CThreadException
exception.
See Also
Stop
SetAttributes
SetStackSize
PostCommand
WaitForNotification
Back to CThread
CThread::Stop
BOOL CThread::Stop(DWORD& dwExitCode, DWORD
dwTimeout = CThread::DW_INFINITE)
throws CThreadException of type:
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
This method
stops the WINDOWS running thread connected to CThread
object. Used
in the owner thread. In notificable threads Stop() method fires
CThread::CMD_STOP Command immediately after the WINDOWS thread was asked to be
stopped. CThread::CMD_STOP Command must be handled in ThreadHandler
method to properly terminate the thread. If CThread
object does not
support Thread Notification, Stop() will wait until the WINDOWS thread actually
terminates. In both modes the method returns only in the case when the WINDOWS
thread actually terminates, the timeout interval elapses or some significant
error occurs. Otherwise it waits (synchronous stopping). When an immediate
return is required the user may set 'dwTimeout' variable to zero. In such case,
however, the user is responsible to find out if the thread actually runs or is
already stopped.
Return Value
Stop return status
- TRUE
- WINDOWS thread was properly stopped.
- FALSE
- WINDOWS thread was not stopped after the timeout interval elapsed.
Parameters
- dwExitCode
[out] WINDOWS thread exit code.
dwTimeout
[in] Timeout interval in tenths of second.
See Also
Start
PostCommand
WaitForNotification
Back to CThread
CThread::ThreadHandler
DWORD CThread::ThreadHandler(void)
Main CThread-handler virtual abstract method declaration.
This method
is not implemented in the CThread
class and must be implemented at
least at one CThread
-Derived class in the CThread
class hierarchy. ThreadHandler()
method concentrates the whole task
that CThread
thread has to execute. The implementation itself
varies according to the type of CThread
thread operating on this
method (Trivial or Notificable Threads).
For Notificable CThread
threads the method contains a main loop with the
WaitForNotification method resolving incoming commands fired from the
owner thread.
Detailed information as well as the examples how to
implement, manage and use this method for both Trivial and Notificable
CThread
threads can be found in the 'Developer.doc'
documentation.
Return Value
Thread task completion exit code. Developers may define an arbitrary exit
code here except the WINDOWS predefined constant = STILL_ACTIVE (0x00000103L),
which indicates the thread-is-alive status.
See Also
PostCommand
WaitForNotification
HandleCommandImmediately
Back to CThread
CThread::Unlock
void CThread::Unlock(void)
Marks the end of the critical code in Thread-Handler-Oriented synchronization
mode. This method must be preceded by Lock method.
Important note:
Both Lock()
and Unlock()
methods may
be called from within the appropriate CThread
thread only (represented by the
ThreadHandler()
method body). The methods should not be published and cannot be
delegated to other threads - otherwise unpredictable deadlocks may arise.
See Also
Lock
Back to CThread
CThread::WaitForActivityStatus
BOOL CThread::WaitForActivityStatus(int
nActivityStatus, DWORD dwTimeout = CThread::DW_INFINITE)
Waits until the desired CThread
activity status is reached. Used
in the owner thread. This is a "good-servant-but-bad-master" method. The
owner thread may fire an arbitrary command to the CThread
object by
the PostCommand method. That means, the PostCommand method fires a
command and returns immediately. However, in some cases the owner thread may
want to wait until the command is actually handled. For this reason the process
may use this method which waits until the desired activity status is set in the
ThreadHandler method. In this case the user is responsible to set the
desired activity status in the ThreadHandler by the
SetActivityStatus method. Using of this method requires an
implementation of the proper 'set-thread-activity-status' strategy. If, for
example, the desired activity status is not properly set or is immediately
rewritten by another value, the desired status is consequently never reached and
the WaitForActivityStatus()
method hangs. Sometimes the thread-synchronization
locking mechanism is necessary. WaitForActivityStatus()
method returns only
in the case when the desired activity status was actually reached or timeout
interval elapsed.
Note: The Start()
and Stop()
methods do not
have to be checked by this method. These methods are executed synchronously and
return when the CThread-thread actually starts or stops.
Important
note: If the CThread
thread utilizes the main
application message queue be aware of using this method. WaitForActivityStatus()
method blocks the application thread from which is called and may not allow the
CThread
thread to complete its task requiring the message queue
handling. This may lead to a deadlock. For more information see 'Developers.doc'
documentation.
Return Value
TRUE if the desired activity status is reached; FALSE if the timeout elapsed
OR the thread has been prematurely terminated before the desired status was
reached. Developers should always check this return value if there is no an
explicit guaranty about the thread's lifetime.
Parameters
- nActivityStatus
[in] Desired CThread
activity status that is to be reached.
dwTimeout
[in] Timeout interval in tenths of second.
See Also
SetActivityStatus
PostCommand
ThreadHandler
Back to CThread
CThread::WaitForNotification
void CThread::WaitForNotification(int&
nIncomingCommand, DWORD dwDefaultTimeout =
CThread::DW_INFINITE)
The main ThreadHandler notification method. This method must be
implemented inside the ThreadHandler method for Notificable CThread
threads (see 'Developer.doc' documentation). The method waits for
incoming notifications (commands) fired from the owner thread via
PostCommand method and returns immediately after the command was
received. Returned command has to be handled in ThreadHandler method.
User may, however, set the timeout interval which forces the method to
return after the timeout interval elapses.
This method is valid only if
CThread
-Derived class supports Thread Notification. Thread
Notification can be established by adding SUPPORT_THREAD_NOTIFICATION macro in
CThread
-Derived class constructor in which ThreadHandler
method is actually implemented. Otherwise it has no any effect and the method
returns immediately. This method is usable after the CThread
thread has been successfully started.
Detailed information how to
use this method as well as how to manage fired commands in the thread task
handler can be found in the 'Developer.doc' documentation.
Parameters
- nIncomingCommand
[out] Reference to the Command ID that was fired from within the owner
thread.
dwDefaultTimeout
[in] Timeout interval in 'miliseconds'.
See Also
PostCommand
CThread
Predefined
Commands
Back to CThread
CThread::~CThread
CThread::~CThread(void)
CThread
destructor. CThread
destructor kills the
running WINDOWS thread that was not previously stopped and closes the
CThread
notification mode.
Back to CThread
CThreadException class
CThreadException class CThreadException: public CException
CThreadException Class Members
Class Members
Public Members:
- CThreadException(CThread*
pThread = NULL)
- CThreadException Constructor
- CThreadException(CThread*
pThread, CString strErrorMsg, int nExceptionType =
CThreadException::UNKNOWN_ERROR)
- CThreadException Constructor
- CThreadException(CThread*
pThread, UINT nErrorMsgID, int nExceptionType =
CThreadException::UNKNOWN_ERROR)
- CThreadException Constructor
- CThread*
GetThread()
const
- Get
CThread
Object
- CString
GetErrorMsg()
const
- Get Error Message
- int
GetType() const
- Get Type of Thrown Exception
- virtual int
ReportError(UINT nType = MB_OK,
UINT nMessageID = 0)
- Report Error
- static CString
GetLastSystemErrorMsg(DWORD
dwSysErrorCode)
- Get String Representation Corresponding to the System Error Code
Class Members
Protected Members:
- void
SetThread(CThread*
pThread)
Set CThread
Object Throwing an Exception
void SetErrorMsg(CString
strErrorMsg)
Set Error Message
void SetErrorMsg(UINT
nErrorMsgID)
Set Error Message
void SetType(int nType)
Set Exception Type
CThreadException::CThreadException
CThreadException::CThreadException(CThread* pThread,
CString strErrorMsg, int nExceptionType =
CThreadException::UNKNOWN_ERROR)
CThreadException constructor. General CThreadException class intended to be
used by CThread
-Derived classes. CThread
-Derived
methods should always throw CThreadException exceptions. To distinguish the
origin of thrown exceptions the user should use the type of CThreadException
exception. CThread
methods use predefined CThreadException types
but the user may define own types in CThread
-Derived class.
Predefined types used in CThread
class are described in
'Parameters' section.
Parameters
- pThread
[in] CThread
object causing an exception.
strErrorMsg
[in] String describing an exception origin.
nExceptionType
[in] Type of thrown exception.
CThreadException::UNKNOWN_ERROR
Exception origin not known.
CThreadException::CANNOT_CREATE_THREAD
WINDOWS Thread cannot be created.
CThreadException::THREAD_ALREADY_STARTED
Thread is already started.
CThreadException::CANNOT_TERMINATE_THREAD
Thread termination failed.
CThreadException::CANNOT_CREATE_NOTIFICATION_OBJECT
Internal notification error.
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Internal notification error.
See Also
SetThread
SetType
Back to CThreadException
CThreadException::CThreadException
CThreadException::CThreadException(CThread*
pThread,
UINT nErrorMsgID, int nExceptionType =
CThreadException::UNKNOWN_ERROR)
CThreadException
constructor. General CThreadException
class intended to be
used by CThread
-Derived classes. CThread
-Derived
methods should always throw CThreadException
exceptions. To distinguish the
origin of thrown exceptions the user should use the type of CThreadException
exception. CThread
methods use predefined CThreadException
types
but the user may define own types in CThread
-Derived class.
Predefined types used in CThread
class are described in
'Parameters' section.
Parameters
- pThread
[in] CThread
object causing an exception.
nErrorMsgID
[in] Resource ID of the string describing an exception origin.
nExceptionType
[in] Type of thrown exception.
CThreadException::UNKNOWN_ERROR
Exception origin not known.
CThreadException::CANNOT_CREATE_THREAD
WINDOWS Thread cannot be created.
CThreadException::THREAD_ALREADY_STARTED
Thread is already started.
CThreadException::CANNOT_TERMINATE_THREAD
Thread termination failed.
CThreadException::CANNOT_CREATE_NOTIFICATION_OBJECT
Internal notification error.
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Internal notification error.
See Also
SetThread
SetType
Back to CThreadException
CThreadException::CThreadException
CThreadException::CThreadException(CThread*
pThread = NULL)
CThreadException constructor. General CThreadException class intended to be
used by CThread
-Derived classes.
Parameters
- pThread
[in] CThread
object causing an exception.
See Also
SetThread
Back to CThreadException
CThreadException::GetErrorMsg
CString
CThreadException::GetErrorMsg(void)
Gets an error message describing an exception origin.
Return Value
Error message string describing an exception.
See Also
SetErrorMsg
Back to CThreadException
CThreadException::GetLastSystemErrorMsg
static CString
CThreadException::GetLastSystemErrorMsg(DWORD
dwSysErrorCode)
Static method which returns the message text corresponding to the system
error code. This error code should be returned by GetLastError() WINDOWS
function immediately after the system error occurs.
Return Value
String representation of the system error code.
Parameters
- dwSysErrorCode
[in] System error code returned by GetLastError() WINDOWS function.
Back to CThreadException
CThreadException::GetThread
CThreadException::GetThread(void)
Gets CThread
object that caused an exception.
Return Value
CThread
object that caused an exception.
See Also
SetThread
Back to CThreadException
CThreadException::GetType
int
CThreadException::GetType(void)
Gets the type of an exception. Types used in the CThread
class
are described in 'Return Value' section.
Return Value
Predefined types that may be thrown by CThread
methods are as
follows:
- CThreadException::UNKNOWN_ERROR
- Exception origin not known.
- CThreadException::CANNOT_CREATE_THREAD
- WINDOWS Thread cannot be created.
- CThreadException::THREAD_ALREADY_STARTED
- Thread is already started.
- CThreadException::CANNOT_TERMINATE_THREAD
- Thread termination failed.
- CThreadException::CANNOT_CREATE_NOTIFICATION_OBJECT
- Internal notification error.
- CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
- Internal notification error.
See Also
SetType
Back to CThreadException
CThreadException::ReportError
int
CThreadException::ReportError(UINT nType =
MB_OK, UINT nMessageID = 0 )
Displays an exception-error message in the standard Message Box.
Return Value
Message Box return value.
Parameters
- nType
[in] Type of the Message Box to be displayed.
nMessageID
[in] Error message string resource ID.
Back to CThreadException
CThreadException::SetErrorMsg
void CThreadException::SetErrorMsg(CString
strErrorMsg)
Sets an error message describing an exception origin.
Parameters
- strErrorMsg
[in] Error message string.
See Also
GetErrorMsg
Back to CThreadException
CThreadException::SetErrorMsg
void CThreadException::SetErrorMsg(UINT nErrorMsgID)
Sets an error message describing an exception origin.
Parameters
- nErrorMsgID
[in] Error message string resource ID.
See Also
GetErrorMsg
Back to CThreadException
CThreadException::SetThread
void CThreadException::SetThread(CThread* pThread)
Sets CThread
object that caused an exception.
Parameters
- pThread
[in] CThread
object that caused an exception.
See Also
GetThread
Back to CThreadException
CThreadException::SetType
void CThreadException::SetType(UINT nErrorMsgID)
Sets the type of an exception. CThread
-Derived methods should
always throw CThreadException
exceptions. To distinguish the origin of thrown
exceptions the user may define own types of CThreadException
exceptions in the
CThread
-Derived class. Predefined types used in CThread
class are described in 'Parameters' section.
Parameters
- nErrorMsgID
[in] Exception type.
CThreadException::UNKNOWN_ERROR
Exception origin not known.
CThreadException::CANNOT_CREATE_THREAD
WINDOWS Thread cannot be created.
CThreadException::THREAD_ALREADY_STARTED
Thread is already started.
CThreadException::CANNOT_TERMINATE_THREAD
Thread termination failed.
CThreadException::CANNOT_CREATE_NOTIFICATION_OBJECT
Internal notification error.
CThreadException::CANNOT_SIGNAL_NOTIFICATION_OBJECT
Internal notification error.
See Also
GetType
Back to CThreadException
CThread
Activity Status Predefined Values
enum <CODE>CThread Activity Status Predefined Values {
THREAD_CREATED,
THREAD_STOPPED,
THREAD_RUNNING,
THREAD_PAUSED,
THREAD_CONTINUING,
THREAD_PENDING,
THREAD_USER_ACTIVITY,
};
Members
- THREAD_CREATED
Thread was successfully created (activity-status set by the Start() method).
THREAD_STOPPED
Thread is stopped.
THREAD_RUNNING
Thread is running.
THREAD_PAUSED
Thread is paused.
THREAD_CONTINUING
Thread is continuing.
THREAD_PENDING
Thread is pending.
THREAD_USER_ACTIVITY
Base offset for the user-defined activity status.
CThread
General Predefined Values
enum <CODE>CThread General Predefined Values {
DW_OK,
DW_ERROR,
DW_UNDEFINED,
DW_TIMEOUT_ELAPSED,
DW_INFINITE,
};
Members
- DW_OK
Exception origin not known.
DW_ERROR
WINDOWS Thread cannot be created.
DW_UNDEFINED
Thread is already started.
DW_TIMEOUT_ELAPSED
Thread termination failed.
DW_INFINITE
Infinite Timeout Interval.
CThread
Predefined Commands
enum <CODE>CThread Predefined Commands {
CMD_NONE,
CMD_TIMEOUT_ELAPSED,
CMD_INITIALIZE,
CMD_RUN,
CMD_PAUSE,
CMD_CONTINUE,
CMD_RESET,
CMD_STOP,
CMD_USER_COMMAND,
};
Members
- CMD_NONE
No command received.
CMD_TIMEOUT_ELAPSED
Wait-timeout elapsed (not command).
CMD_INITIALIZE
Initialize thread task.
CMD_RUN
Run thread task.
CMD_PAUSE
Pause thread task.
CMD_CONTINUE
Continue thread task.
CMD_RESET
Reset thread task.
CMD_STOP
Stop thread task and leave controlling function.
CMD_USER_COMMAND
Base offset for the user-defined command.
CThreadException Predefined Types
enum CThreadException Predefined Types {
UNKNOWN_ERROR,
CANNOT_CREATE_THREAD,
THREAD_ALREADY_STARTED,
CANNOT_TERMINATE_THREAD,
CANNOT_CREATE_NOTIFICATION_OBJECT,
CANNOT_SIGNAL_NOTIFICATION_OBJECT,
};
Members
- UNKNOWN_ERROR
Exception origin not known.
CANNOT_CREATE_THREAD
WINDOWS Thread cannot be created.
THREAD_ALREADY_STARTED
Thread is already started.
CANNOT_TERMINATE_THREAD
Thread termination failed.
CANNOT_CREATE_NOTIFICATION_OBJECT
Internal notification error (not enough memory or access denied).
CANNOT_SIGNAL_NOTIFICATION_OBJECT
Internal notification error (not enough memory or access denied).