In Java, the thread runs a running object. The object of the object is in JTC C is a JTCRunnable. That is, an object entity running. The thread itself is an object, and the entity to run in the thread is also an object. JTCRunnable
============================================================================================================================================================================================================= ===
Main object:
Class Clock: Public JTRNABLE
{
Void run (); // When the thread start is called
Void start (); // Start thread
Void stop (); // Stop thread
}
============================================================================================================================================================================================================= ===
In fact, JTCRunable is very simple, only one virtual method, only Run is the method we have to fully realize.
Class JTCRUNNABLE: Public Virtual JTCREFCOUNT
{
PUBLIC:
Virtual void Run () = 0;
}
============================================================================================================================================================================================================= ===
We can see that the inheritance of the JTCRunable is a reference count class.
Class JTCREFCOUNT
{
PUBLIC:
Long m_refcount;
Add and reduce references by interlocked under Win32.
A MUTEX is required under UNIX to protect the reference.
#ifndef Win32
JTCMUTEX M_REF_MUTEX;
#ENDIF
JTCREFCOUNT ()
: m_refcount (0)
{
}
Virtual
~ Jtcrefcount ()
{
}
}
============================================================================================================================================================================================================= ===
Thread will run the entity
Run ()
{
While (Timer_)
Try {
Timer_ -> Sleep (100);} catch (const jtcinterruptedexception)
{}
}
============================================================================================================================================================================================================= ===
The function implements the entity code running. Need a vector to run him
Start ()
{
Timer_ = New JTCTHREAD (JTRunnableHandle (this));
Timer_ -> start (); // thread startup,
// The function start of the specific JTCThread:
POSIX-> pthread_create
Windows -> _BEGINTHREADEX
Create a hang-haunted thread. Run () function is related to the thread.
}
============================================================================================================================================================================================================= ===
After the thread is stopped, the thread handle in the primary object is empty.
Void Stop ()
{
Timer_ = jtcthreadhandle ();
}
============================================================================================================================================================================================================= ===
Main object clock call:
Main ()
{
Try
{
JTCinitialize Bootjtc (Argc, Argv);
JTCHANDLET
C -> Start ();
JTCTHREAD :: Sleep (1000 * 5);
C -> stop ();
}
Catch (Const JTCException & E) {
CERR << "JTCEXCEPTION: << E.GetMessage () << endl;
}
}
============================================================================================================================================================================================================= === The constructor of the thread is initialized by the init member function.
JTCTHREAD :: JTCTHREAD (const char * name)
{INIT (JTCTHREADGROUPHANDLE (0), JTCRUNNABLEHANDLE (0), NAME);
JTCTHREAD :: JTCTHREAD (JTCRunnableHandle Target, Const Char * Name)
{INIT (JTCTHREADGROUPHANDLE (0), Target, Name);
JTCTHREAD :: JTCTHREAD (JTCTHREADGROUPHANDE & GROUP, Const Char * Name)
{INIT (Group, JTCRunnableHandle (0), Name);
JTCTHREAD :: JTCTHREAD (JTCTHREADGROUPHANDE & GROUP,
JtcrunnableHandle Target, Const Char * Name)
{INIT (Group, Target, Name);
============================================================================================================================================================================================================= ===
Void
JTCTHREAD :: INIT (
Const JTCTHREADGROUPHANDLE & GROUP,
JTCRunnableHandle Target,
Const char * name
)
{
m_name = 0; // Initial thread name
m_target = target; // initially running target main body
m_state = new_thread; // Initial thread status
m_thread_id = jtcthreadId (); // Initial thread ID
m_detached = false; // Non Win32
m_thread_number = GET_NEXT_THREAD_NUMBER (); // ourselves
m_refcount; // count count
m_is_adopted = false;
m_handle = 0; // Win32 thread handle
m_group = group; // thread group
}
============================================================================================================================================================================================================= === Important is JTCRunnableHandle Target;
Defined as follows:
Class JTCTHREAD;
Typedef JTCHANDLET
Class JTCTHREADGROUP;
Typedef JTCHANDLET
Class JTCRunnable;
Typedef JTCHANDLET
============================================================================================================================================================================================================= ===
Here, template JTCHANDLET is used, providing assignment and comparison operations
Template
Class JTCHANDLET {
JTCHANDLET (T * Tg = 0);
JTCHandlet (Const JTCHandlet
Operator =
Operator ==
Operator! =
Operator!
Operator bool
Operator -> ()
Operator *
T * m_object;
}
The class points to the object through the M_Object pointer.
The template class encapsulates JTCTHREAD, JTCTHREADGROUP, JTCRunable class pointer operation,
For example: In the Start function of the Clock class, create a thread statement:
Timer_ = New JTCTHREAD (JTRunnableHandle (this));
That is, an instance pointer of a class of JTCRunable class.
JTCTHREAD
============================================================================================================================================================================================================= ===
Class JTCTHREAD: PUBLIC Virtual JTCREFCOUNT
{
}
================================================== === JTCThread in the run actually calls the run method of constructing an incoming object initialization m_target
Void JTCTHREAD :: Run ()
{
IF (m_target)
{
M_Target -> Run ();
}
}
============================================================================================================================================================================================================= ===
Start the thread, create a thread execution.
Void Jtcthread :: Start ()
{
//statement
JTCSYNCT
// Judge whether the current thread is not new thread.
IF (m_state! = jtcthread :: new_thread)
{
throw JTCIllegalThreadStateException ( "state is not new_thread");
}
Different POSIX and WIN32 implementation
#if Defined (Have_posix_threads)
... ..
#ifdef Have_win32_threads
......
}
============================================================================================================================================================================================================= ===
Thread creation implementation under UNIX
#if Defined (Have_posix_threads)
PTHREAD_ATTR_T ATTR;
Try {
JTC_SYSCALL_1 (pthread_attr_init, & attr,! = 0)
} Catch (const jtcsystemcallexception & e) {
IF (E.GETERROR () == enomem) {
Throw JTCOUTOFMEMORYERROR (E.GetMessage ());
}
Throw;
}
# If defined (HAVE_POSIX_THREADS) &&! Defined (__ hpux)
// All threads set their prior xiX 11.x this
// Requires root privilege so it's disabled.
PTHREAD_ATTR_SETINHERITSCHED (& Attr, pthread_explicit_sched); # Endif
# Neydef Have_Pthread_attr_setstacksize
IF (LSD_Initial_stack_size! = 0) {
Pthread_attr_setstacksize (& Attr, LSD_INITIAL_STACK_SIZE);
}
# Endif
// Call The Custom Pthread Attribute Hook, IF Defined.
IF (SM_ATTR_HOOK! = 0) {
(* SM_ATTR_HOOK) (& ATTR);
}
PTHREAD_T ID;
Try {
Pthread_create (ID, Attr, LSF_THREAD_ADAPTER, THIS)
} Catch (const jtcsystemcallexception & e) {
Pthread_attr_destroy (& attr);
IF (E.GETERROR () == EAGAIN || E.Geterror () == enomem) {
Throw JTCOUTOFMEMORYERROR (E.GetMessage ());
}
Throw;
}
m_thread_id = jtcthreadID (ID);
Pthread_attr_destroy (& attr);
#ENDIF
============================================================================================================================================================================================================= ===
Thread creation implementation under Win32
#ifdef Have_win32_threads
DWORD ID;
Try
{
JTC_SYSCALL_6 (
M_Handle = (Handle) :: _ BeginThreadex,
NULL, LSD_INITIAL_STACK_SIZE,
(unsigned (__stdcall *)) LSF_thread_adapter, (lpvoid) this,
0, (unsigned int *) & id, == NULL)
}
Catch (Const JTCSystemcallexception & E)
{
IF (E.GETERROR () == Error_not_ENUGH_MEMORY ||
E.Geterror () == Error_OutofMemory)
{
Throw JTCOUTOFMEMORYERROR (E.GetMessage ());
}
Throw;
}
m_thread_id = jtcthreadID (ID);
#ENDIF
============================================================================================================================================================================================================= ======== Sleep () function is a very independent function, there is no major relationship with its own thread
Void JTCTHREAD :: Sleep (Long Millis, Int nano)
{
IF (Millis <0)
{
Throw JTCillegalargumentException
("Timeout Value Is Negative");
}
IF (nano> 999999)
{
Throw JTCillegalargumentException
("Nanosecond Timeout Out of Range";
}
// m_state = jtcthread :: not_runnable;
#if Defined (have_pthread_delay_np)
Struct Timespec TV;
TV.TV_SEC = Millis / 1000;
TV.TV_NSEC = (Millis% 1000) * 1000000 nano;
JTC_SYSCALL_1 (pthread_delay_np, & TV,! = 0);
#elif defined (Have_posix_threads)
Struct Timespec TV;
TV.TV_SEC = Millis / 1000;
TV.TV_NSEC = (Millis% 1000) * 1000000 nano;
IF (NanoSleep, 0) <0 && errno == EINTR)
{
Throw JTCINTERRUPTEDEXCEPTION ();
}
#ENDIF
#ifdef Have_win32_threads
Sleep (millis); // Call Windows API
#ENDIF
// m_state = jtcthread :: Runnable;
}
============================================================================================================================================================================================================= =========
JTCMonitor inherits from JTCMonitorBase, members are relatively simple
Class JTCMonitor: Public JTCMonitorBase
{
// Outside the naked three public functions
Wait ();
Notify ()
NotifyAll ();
// There are three important private functions inside.
Lock ()
unloack ();
Notify_internal ()
// We pay attention to even two friends
Friend class JTCSYNCHRONIZED;
Friend Class JTCSYNCT
// The last is a mutually exclusive member JTCRECURSIVEMUTEX M_MON_MUTEX;
}
============================================================================================================================================================================================================= =========
JTCMonitorBase is also relatively simple
Class JTCMonitorBase
{
/ / Check if Mornitor is locked
Validate_owner (Const JtcthreadID, Const Char * Caller)
// mornitor condition variable
JTCCOND M_MON_COND;
// Record how much hang notification
INT M_NNOTIFY
}
============================================================================================================================================================================================================= =========
How do JTCMonitor and JTCSYNCHRONIZED do?
The definition of JTCSynchronized is also simple, mainly to define several member variables. Three mutex variables have been defined.
Class JTCSYNCHRONIZED
{
JTCMonitor * M_Monitor
JTCMUTEX * M_MUTEX
JTCRecursivemutex * m_rmutex
JTCRWMUTEX * M_RWMUTEX
}
M_Monitor points to the need to monitor entity;
M_Mutex points to the connected mutual exclusion entity
M_rmutex points to the mutual exclusive entity of Connected Recursive
M_RWMUTEX points to read and write mutual exclusion
Class constructor
JTCSYNCHRONIZED (Const JTCMonitor & Mon);
M_Monitor (& Mon),
M_Lock_Type (Monitor)
{
// In fact synchronization class, use the constructed monitor to lock
M_Monitor -> Lock ();
}
-------------------------------------------
Other constructs are similar, using the constructed entity to lock
JTCSYNCHRONIZED :: JTCSYNCHRONIZED (Const JTCMutex & M)
: M_Mutex (& M),
m_lock_type (MUTEX)
{
M_Mutex -> Lock ();
}
--------------------------------------------
JTCSYNCHRONIZED :: JTCSYNCHRONIZED (
Const JTCRecursivemutex & M
)
: M_rmutex (& M),
M_Lock_Type (Recursive_Mutex)
{
M_rmutex -> Lock ();
}
-----------------------------------------------
JTCSYNCHRONIZED :: JTCSYNCHRONIZED (
Const JTCRWMUTEX & M, READWRITELOCKTYPE TYPE
)
: M_RWMUTEX (& M),
m_lock_type (read_write_mutex)
{
IF (Type == Read_Lock)
M_RWMUTEX -> Read_lock ();
Else
M_RWMUTEX -> WRITE_LOCK ();
}
============================================================================================================================================================================================================= =========
For an application example:
Example Testthread inherited JTCMornitor, using synchronous SYNC, using synchronous SYNC, instance of TestthRead
This is a construction parameter. This way is a role.
Class testthread: Public JTCTHREAD, PUBLIC JTCMONITOR
{
Run ()
{
JTCSYNCHRONIZED SYNC (* THIS);
/ / Here, in fact, call the inherited JTCMonitor Lock () function, the lock is saved
The defined JTCRecursiveMutex member variable m_mon_mutex in JTCMonitor ..
// The next step is to look at the mutual definition.
// do your code here
......
}
}
============================================================================================================================================================================================================= =========
First go back to see the realization of the lock () function
Void JTCMonitor :: Lock () Const
{
// jtcmonitor itself's mutual exclusion variable is shackled
IF (M_MON_MUTEX.LOCK ()) {
// First m_nnotify is 0
JTCMonitor * this = (jtcmonitor *).
THIS -> M_NNNNOTIFY = 0;
}
}
============================================================================================================================================================================================================= =========
Class JTCRecursivemutex
{
// Above the lock function
LOCK ();
unlock ();
TRYLOCK ();
Get_owner ();
COUNT ();
// internal implementation lock function
LOCK_INTERNAL (); trylock_internal ();
unlock_internal ();
RESET_FOR_CONDVAR ();
// The definition of the platform is now.
#if Defined (Have_posix_threads)
PTHREAD_MUTEX_T M_LOCK; // Pthreads Mutex.
#ENDIF
#if Defined (have_win32_threads)
Critical_section m_lock; // Win32 critical section.
#ENDIF
// member definition
JTCMUTEX M_INTERNAL; / / internal lock
Unsigned int m_count; / /
JTCTHREADID M_OWNER; / / Plock Thread ID
Friend class jtccondhelper;
Friend class jtccond;
}
============================================================================================================================================================================================================= =========
At the LOCK () call, the JTCRecursiveMutex class is linked through JTCMutex.
Look at the call lock () function, what happened?
Bool
JTCRecursivemutex :: Lock () Const
{
//
// Work Around lack of mutable.
//
Return ((JTCRecursivemutex *) THIS -> LOCK_INTERNAL (1);
}
============================================================================================================================================================================================================= =========
LOCK_INTERNAL () function implementation
Bool JTCRecursivemutex :: LOCK_INTERNAL (INT Count)
{
BOOL RC = false;
BOOL OBTAINED = FALSE;
While (! Obtained)
{
-------------------------------------------------- -------------------------
m_internal.lock ();
IF (m_count == 0)
{
m_count = count;
M_OWNER = JTCTHREADID :: Self ();
Obtained = true;
Rc = true;
Try
{
#if Defined (Have_posix_threads)
JTC_SYSCALL_1 (PTHREAD_MUTEX_LOCK, & M_LOCK,! = 0)
#ENDIF
#if Defined (have_win32_threads)
ENTERCRITICALSECTION (& M_LOCK); # ENDIF
}
Catch (...)
{
Try {
m_internal.unlock ();
} catch (...)
{
}
Throw;
}
}
Else if (m_owner == jtcthreadid :: self ()))
{
m_count = count;
Obtained = true;
}
m_internal.unlock ();
-------------------------------------------------- -------------------------
IF (! Obtained)
{
#if Defined (Have_posix_threads)
JTC_SYSCALL_1 (PTHREAD_MUTEX_LOCK, & M_LOCK,! = 0)
PTHREAD_MUTEX_UNLOCK (& M_LOCK);
#ENDIF
#if Defined (have_win32_threads)
ENTERCRITICALSECTION (& M_LOCK);
LeavecriticalSection (& M_Lock);
#ENDIF
}
}
Return RC;
}
============================================================================================================================================================================================================= =========
JTCMUTEX is used inside the function as an internal lock, and it is time to see the JTCMutex class.
Class JTCMUTEX
{
-------------------------------------------------- ------------------
LOCK ();
unlock ();
TRYLOCK ();
Get_owner ();
COUNT ();
-------------------------------------------------- ------------------
// Platform related member definition
#if Defined (Have_posix_threads)
PTHREAD_MUTEX_T M_LOCK; // Pthread Mutex.
#ENDIF
#if Defined (have_win32_threads)
Critical_section m_lock; // Win32 critical section.
#ENDIF
-------------------------------------------------- ------------------
Friendly definition
Friend class jtccond;
}
============================================================================================================================================================================================================= =========
Lock () function of UNIX implementation {
#if Defined (Have_posix_threads)
#if Defined (__ gnuc__) && defined (__ Optimize__)
//
// The Optimizer for GCC 2.95.1 is Broken. The Following
// Three Lines of code "FIX" the problem.
//
Volatile INT I = 1;
IF (i == 0)
i;
#ENDIF
PTHREAD_MUTEX_T * LOCK = & ((JTCMUTEX *) THIS -> M_LOCK;
JTC_SYSCALL_1 (PTHREAD_MUTEX_LOCK, LOCK,! = 0)
#ENDIF
}
Lock () function Win32 implementation
{
#if Defined (have_win32_threads)
Critical_section * crit = & (jtcmutex *) THIS) -> M_LOCK;
ENTERCRITICALSECTION (CRIT);
#ENDIF
}
============================================================================================================================================================================================================= =========
Back to the class definition of previous JTCMornitorBase, there is a member of condition variables
JTCCOND M_MON_COND;, in the wait () function of the class of JTCMornitor, use him
Void JTCMonitor :: wait ()
{
Validate_owner (m_mon_mutex.get_owner (), "Wait ()");
Notify_internal (m_nnotify); // int m_nnotify number hangs
Try
{
// JTCRECURSIMUTEX M_MON_MUTEX; Waiting for Monored Mutual Exclusion
m_mon_cond.wait (m_mon_mutex);
}
Catch (...)
{
m_nnotify = 0;
Throw;
}
m_nnotify = 0;
}
============================================================================================================================================================================================================= =========
Conditional variable class, he implements a notification of the object by constructing the waiting condition object that is introduced into the function.
For example: Multiple threads wait for a thread's mutual exclusive condition, and notify each thread after a moment is released.
Class JTCCOND
{
Wait (JTCRecursivemutex & Mutex);
Wait (JTCMUTEX & MUTEX);
Signal ();
Broadcast ();
WAIT_INTERNAL (JTCRECURSIMUTEX &, Long Timeout); Calc_timeout; // Posix
// Platform related member variable definition
#if Defined (Have_posix_threads)
Pthread_cond_t m_cond; // pthread condition variable.
#ENDIF
#if Defined (have_win32_threads)
CondImpl * m_impl;
#ENDIF
}
The wait () function simply calls the internal WAIT_INTERNAL () function, waiting for the mutual exclusion condition
JTCCond :: Wait (JTCRecursivemutex & Mutex)
{
WAIT_INTERNAL (MUTEX, -1);
}
First look at Win32 implementation
#if Defined (have_win32_threads)
WAIT_Internal (JTCRecursivemutex & Mutex,)
{
M_Impl -> pre_wait ();
Unsigned int count = mutex.reset_for_condvar ();
Try
{
/ / Call the WAIT function of the internal condition class, the internal use of the signal is implemented
BOOL RC = m_Impl -> Wait (Timeout);
Mutex.lock (count);
Return RC;
}
Catch (...)
{
Mutex.lock (count);
Throw;
}
#ENDIF
}
The main focus is in the function m_impl-> Wait () of the member variable
CondImpl * m_impl
Bool Condimpl :: Wait (Long Timeout)
{
// Wait for the Queue Semaphore to Be Signaled.
Try {
BOOL RC = m_queue.wait (Timeout);
Postwait (! rc);
Return RC;
} catch (...)
{
Postwait (FALSE);
Throw;
}
}
Discover a queue member variable and send a postwait () function. Let's take a look at the definition of condImpl
============================================================================================================================================================================================================= =========
Class condimpl
{
Signal ();
pre_wait ();
Wait ();
Postwait ();
// Key member definition
JTCSemaphore M_Gate;
JTCSemaphore M_Queue; // can be said to be a signal queue
JTCMUTEX M_INTERNAL; / / It is used inside to lock
Long m_blocked;
Long m_unblocked;
Long m_to_unblock;
}
============================================================================================================================================================================================================= ======== Member M_Queue Although the queue, he is implemented by the signal.
Class JTCSemaphore
{
JTCSEMAPHORE (long initial_count = 0);
~ Jtcsemaphore ();
// Wait and POST realize the semaphore waiting and delivery
BOOL WAIT (long timeout = -1);
Void Post (int count = 1);
#if Defined (have_win32_threads)
Handle M_Sem; // The Semaphore Handle
#ENDIF
}
The constructor calls the createMaphore (); function, the amount of semaphore is 0x7fffffff when creating.
The starting semaphore is initialized to constructor.
JTCSemaphore :: jtcsemaphore (long initial_count)
{
#if Defined (have_win32_threads)
JTC_SYSCALL_4 (m_sem = cretesemaphore, 0, initial_count, 0x7ffffff, 0,
== Invalid_Handle_Value)
#ENDIF
}
When the signal is greater than 0, the friend signal, no signal is equal to 0.
Win32's semaphore implementation calls WaitForsingleObject and ReleaseSemaphore functions.
When the signal is 0, Wait () is always waiting, if the function returns when the signal is greater than 0, the signal is reduced,
And POST () is to add a signal amount.
Bool JTCSemaphore :: Wait (long timeout)
{
#if Defined (have_win32_threads)
IF (Timeout <0) {
Timeout = infinite;
}
Int rc;
JTC_SYSCALL_2 (RC = WaitForsingleObject, m_sem, timeout, == Wait_abandoned);
Return RC! = WAIT_TIMEOUT;
#ENDIF
}
Void JTCSemaphore :: Post (int COUNT)
{
#if Defined (have_win32_threads)
JTC_SYSCALL_3 (ReleaseSemaphore, M_Sem, Count, 0, == 0)
#ENDIF
}
============================================================================================================================================================================================================= =========
Implementation of psotwait ()
Void Condimpl :: Postwait (Bool Timeout)
{
m_internal.lock ();
M_unblocked ;
IF (M_TO_UNBLOCK! = 0)
{
Bool last = (--m_to_unblock == 0);
m_internal.unlock ();
IF (Timeout) {
m_queue.wait ();
}
IF (last) {
m_gate.post ();
} else {
m_queue.post ();
}
} else {
m_internal.unlock ();
}
}
About Syscall
Providing an exception error message and a file name output and the file name output and the file name that occurred during the failure of the important function call. Fn is a function name, others are parameters, and finally the function return value. This approach is worth learning.
#define JTC_SYSCALL_6 (FN, A1, A2, A3, A4, A5, A6, COND) /
DO {/
DECLARE_ERRNO /
IF ((ASSIGN_ERRNO (FN (A1, A2, A3, A4, A5, A6))) COND /
JTC_THROW_EXCEPTION (Errno, #fn << JTC_FMT_ARG_6 (A1, A2, A3, A4, A5, A6)) /
} while (0);
# Define JTC_THROW_EXCEPTION (CODE, MSG) /
{/
Long error = code; /
Char MSG [512]; /
MSG [SIZEOF (MSG) -1] = '/ 0'; /
JTC_STD (OstrStream) stream (MSG, SIZEOF (MSG) -1); /
stream << msg << "==" << Error << "[<< __file__ / /
<< ':' << __line__ << ']' << JTC_STD (ENDS); /
Throw JTCSystemCallexception (MSG, Error); /
}
JTC_STD is about the macro definition of standard flow
#ifndef Have_JTC_NO_IOSTREAM
# I idf Have_STD_IOSTREAM
# Define JTC_STD (x) std :: x
# Else
# Define JTC_STD (x) x
# Endif
#ndif //! Have_JTC_NO_IOSTREAM
Macro definition of function return value
#if Defined (win32)
# Define errno getLastError ()
# Define declare_errno
# Define assign_errno
#ELSE
# Define errno _jtc_syscallerror
# Define declare_ERRNO INT _JTC_SYSCALLERROR;
# Define assign_errno _jtc_syscaller =
#ENDIF