JTC thread library reading analysis

xiaoxiao2021-03-06  102

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 = new clock ();

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 JTCTHREADHANDLE;

Class JTCTHREADGROUP;

Typedef JTCHANDLET JTCTHREADGROUPHANDLE

Class JTCRunnable;

Typedef JTCHANDLET JTCRunnableHandle;

============================================================================================================================================================================================================= ===

Here, template JTCHANDLET is used, providing assignment and comparison operations

Template

Class JTCHANDLET {

JTCHANDLET (T * Tg = 0);

JTCHandlet (Const JTCHandlet & RHS);

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 Guard (m_mutex);

// 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

转载请注明原文地址:https://www.9cbs.com/read-104276.html

New Post(0)