[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference azur::mcc

Title:DECmcc user notes file. Does not replace IPMT.
Notice:Use IPMT for problems. Newsletter location in note 6187
Moderator:TAEC::BEROUD
Created:Mon Aug 21 1989
Last Modified:Wed Jun 04 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:6497
Total number of notes:27359

791.0. "Is a thread running" by SMAUG::DPETERSON () Tue Mar 12 1991 18:58

I'm curious about thread_id management.

Basically the question is "How can I tell if a particular thread is active?"
I suppose one way is to reserved the value 0. This is, if the thread's id is 0
then its not in use. (analogous to the NULL "C" pointer)

I suppose another is mcc_thread_get_attribute() and look for the error
MCC_S_EXISTENCE_ERROR. But because I don't know how ids are allocated
and re-used, it seems like this thread id may not represent my original thread
if it has deleted itself and exited.

And lastly, I could use a state variable that reflects the thread's existence.

How would you guys do it?


thanks

Dave


T.RTitleUserPersonal
Name
DateLines
791.1Try mcc_thread_join_any()TOOK::GUERTINI want my MCCTue Mar 12 1991 20:099
    Use mcc_thread_join_any().  This routine is guaranteed to return only
    when the thread exits, the routine block until then.  Thread_id cannot
    be reused unless you call thread_delete() (and even then I'm not use it
    will be reused). So in other words, let's say worse case you fork off a
    thread and it returns immediately.  You then do a join on that
    thread_id.  It works!  The join comes back right away with the correct
    thread CVR.
    
    -Matt.
791.2but what if it IS runningSMAUG::DPETERSONWed Mar 13 1991 12:3217
    That sounds good if the thread is not running but what if it is.
    Wouldn't my mainline code be blocked until the thread I'm 
    mcc_thread_join_any()'ed with, completes?
    
    Concider this situation. Let's say I've got a thread that processes a
    queue. It completes when the queue is empty. My main line code is
    building the queue. When the main line code decides it's time
    for the queue to be processed, it starts this queue processing thread
    BUT only if the thread is NOT currently active. If it was active,
    that's fine, it would just continue working on the queue, and the
    main line code would continue to add the the queue.
    
    Thread id re-use must still be a concern. My application will
    be (I hope) a very long running process, with many thread creation
    deletion cycles.
    
    Dave
791.3When in doubt, create another threadTOOK::GUERTINI want my MCCWed Mar 13 1991 15:0023
    Okay.  This is (hopefully) just a question of understanding the
    concurrent programming environment that threads provides.
    
    
    Task S :  Dequeue requests and process them
    
    Task Q :  Enqueue requests if there are any
    
    First trial :  Have task Q be the main thread and fork off task S.
    This creates problems because you cannot be guaranteed that task S
    is still there,  how do you know that task S is finished or not?
    
    Second trial :  Have the main thread fork off both Task S AND Task Q.
    First it forks off task Q, then task S.  Then it does a join on task S. 
    When there are no more requests to process, the Main thread will get
    control again.  You can make the algorithm more elaborate by checking
    if Task Q is still running, and restarting Task S if it is.
    
    Would this solve your problem?  I'm not saying that other solutions
    won't work, I'm just recommending using the threading environment to
    it's fullest potential.
       
    -Matt.
791.4mcc_thread_get_attributeTOOK::CALLANDERWed Mar 13 1991 19:0418
Just to continue on from where Matt left off, you can also make use of the
mcc_thread_get_attribute routine. I know in the Notification FM we have setup
all of our threads such that they are named threads. It would be easy to
then (given the thread id) go out and check to see if the thread is still
active by doing a get_attribute for the thread name.

Now, the question is where do you get the thread id from? Well in the 
Notification FM we keep a thread table that is managed by the "main" thread.
It is a dynamically built table. There are a number of ways of keeping
such a table which I don't want to get into here (let's see, I think
the line is "that is left as an excercise for the reader").

By making use of this function your main line thread can go and manage the 
queue, assuming that the dequeuer is there and running, and when it is all
done what it is doing it can test to make sure the dequeuer is still running 
(or whatever order is most convenient for your purpose -- but I degress).

jill
791.5id re-use still bothers meSMAUG::DPETERSONThu Mar 14 1991 12:3741
Thanks for the reply's. They've generated many new ideas I'll incorporate
into my design. 

I think I've clouded the issue by talk about queues and such. Let me
re-state the question and the answer I think I heard, just to be sure.


My question:
I simply need to know how to test if a thread is running.  I want this to
be "poll like". I don't want to be blocked for any reason. The model I'm
using is: the thread creator has at its disposal many special purpose
threads to perform different tasks. As the creator discovers the need for
one of these threads, it will create it, but only if it is not currently
running. The threads do their thing, then a mcc_thread_delete() and return.
Presumably this thread_id is now assignable to other threads.

The answer?
The creator keeps a table of thread names and the thread_id's they were
created with. To test if a thread is active the creator picks the correct
thread_id from its table and does a mcc_thread_get_attribute() for the
thread's name. If it gets a MCC_S_EXISTANCE_ERROR then the thread is not
running. Great we're done. However, if the status is MCC_S_NORMAL then it
must test the returned name against the name in its internal table. If they
match the thread is still active. If they don't the thread is not active
and it's original id has been reused by a different thread.

Have I got it?

Any other methods?
For example:
1-Have the thread set the thread id, in the creators table, to 0 just
before it completes. The creator uses this as its running indicator.
Seems risky and requires special knowledge of possible thread_id values.

2-Have a running indicator in the creator's table which is set by the
creator and cleared by the thread.

Thanks

dave

791.6SOME MORE INFOTOOK::CALLANDERFri Mar 15 1991 13:2225
BTW: Pete B. the expert in this area has been asked to add his two cents on
the subject.

But, for now here is some more of what I know (or assumptions I have based
the notif fm on).

DON"T assume thread id 0 is not a availd id, IT IS! If you want to have
a special character represent a deleted thread I would suggest that your
thread table use signed integers, thread ids are all unsigned, therefore
a negative 1 (or any other negative number) would suffice. To have more
than one thread share access to the thread table remember that locks
are required, but you can pass a pointer to the table (ONLY DO THIS IF THE
TABLE IS DYNAMICALLY ALLOCATED) as an argument to the routine you are
starting on the create thread.


There are no set ways of doing this, so pick what is best for your design.
Please note, Pete D. had a good question after reading my response on using
the get_attribute. He asked about the thread return CVR attribute you would
query. Could this be used? and what is the default value of this attribute
if the thread has not yet returned?

More to think about...
jill's opinions
791.7Data structure -> program structurePETE::BURGESSFri Mar 15 1991 15:59162
I'm confused about the problem you are trying to solve
amidst this discussion of solution techniques.
Could you restate it?  (I don't know of any problem
that has been solved to date by use of mcc_thread_get_attribute)

Basic rule:
With Request/Response type protocols you need to design
your program control structure to correspond with the
structure of the request/response grammar. 
	
It's useful to define "transaction" as a grammar/syntax/structure
of request-response messages that form a basic unit.  One
often assigns a transaction id to this interaction for
convenience of both parties.  There are often other attributes
or context associated with the transaction.  

In simple designs one thread is processes one transaction.
There is simple 1-1 correspondence to the grammar of 
start-transaction, read-1st request, ... end-transaction | abort-transaction
to the processing structure of creating a thread, dequeuing 1st request, ...
terminating a thread.

Variation of designs which are useful:
 
1. Instead of creating/deleting a thread for each transaction,
   o main-control thread creates a pool of n transaction proceessing
     threads, queues, and condition variables, mutexes during its initialation.

   o The main-control thread, which manages multiplexer/demux operations of
     process i/o channels.  Parses the incoming messages into 
	"start-transaction" requests or "request-within-a-transaction".
	if the message is "start-transaction", then
		enque message onto queue of "start-trans" request
		if queue was empty, then MCC_COND_SIGNAL(cv1)
		  (to unblock any idle transaction thread waiting for work (MCC_COND_WAIT(cvr1, mutex1))
		
static mcc_t_condvar cv_start_trans;
static mcc_t_mutex mutex_start_trans;
static xxx_t_queue queue_start_trans;


	else parse the message further finding the transaction-id,
	     map the trans-id to the queue of thread which is processing this transaction.
	     (perhaps, trans-id := sequence queue-id, seq-num endsequence)
	     enqueue message onto thread queue.
	    if queue was empty, then MCC_COND_SIGNAL (cv-queue-id);
		(to unblock transaction thread waiting for next request message of the transaction)

#define N 100 /* Number of transaction threads */
static mcc_t_thread thread_transaction[N];
static mcc_t_mutex mutex_transaction[N];
static mcc_t_condvar cv_transaction[N];


	so main-control thread structure is
		{
		/* do init */
		create start-trans queue, cv, and mutex
		for (i=0, i< N, i++) {
			create mutex [i]
			create cv [i]
			create thread [i]
		}

		do 
			read next input message
			process next input message
		until (error-occurs)
		}		


each transaction thread:
	do_transaction(my_index)
 {
 initialize ();
 
 /* process body of transactions */
 do {
	mcc_mutex_lock (mutex_start_trans);
	while ((dequeue(queue-start-trans, start-trans-request)) != success) {
		status = mcc_cond_wait(cv_start_trans, mutex_start_trans);
		if (status == mcc_s_alert_termreq) {...}
		}
	mcc_mutex_unlock (mutex_start_trans);

	/* start trans */
	assign transaction id = f(my_index, sequence number);
/*	transaction id will appear in all subsequent request/response messages
 *	to map incoming requests to this thread and its processing context.
 *	Invalid transaction ids should be detected.
 */
	begin processing transaction 
	build and send response message ();

	while (trans-not-complete) {
		/* read next request msg */
		mcc_mutex_lock (mutex_trans[my_index]);
		while ((dequeue(queue-trans[my_index], trans-request)) != success) {
			status = mcc_cond_wait(cv_trans[my_index], mutex_trans[my_index]);
			if (status == mcc_s_alert_termreq) {...}
			}
		mcc_mutex_unlock (mutex_trans[my_index]);

		/* process next request msg, producing response message (s) */	
		if (trans-request->request_type == out_of_band) {
			if this a cancellation request? (connection lost, etc), then
			abort_this_transaction
		}					
		else {
			...
		}
	}
  }
  until (fatal-error occurs);
}




variations #2;
  transactions within transactions (hierarchy of concurrent transactions)
  => model transaction threads with same hierarchy

 

Background info on thread states.

Threads states are
	exists
		terminated
		non-terminated
			blocked
			ready to run
			running
	non-existent


I don't know what you mean by "alive".

CVRs of MCC_S_EXISTENCE_ERROR occur when attempting to access
a framework object by its id and the object does not exist.

Note- a thread may terminate and continue to exist for the duration
of the process because it has not been the subject of mcc_thread_delete call.

MCC_THREAD_JOIN_xxxx  blocks the caller until the subject thread has terminated.


MCC_CONTEXT_xxxx rtns are useful.  The context destructor rtns are invoked
when the thread has terminated.




So how come the SRM doesn't document any of the necessary rtns
to design a multiple threaded program?  The plan is to provide
CMA/Pthreads/DECthreads et al in V1.2 of MCC.  V1.0 and V1.1
of DECmcc provide some CMA like capabilities, but we didn't want to
maintain a virtual threads package layer on top of CMA/Pthreads forever.
(But Pthreads interface is not stable ,and CMA threads is 
targetted for obsolence)

791.8question restated & undocumented goodies?SMAUG::DPETERSONWed Mar 20 1991 10:5922
    Oops!
    
    Never say write when you mean reply!
    
    My reply is mistakenly @ note 805.  I'll repeat it here.
    
    
    Pete, Thanks for the help.  The original question has become blurred.
    
    I simply want to know, if there was a method provided by mcc routines
    to tell if a thread is still running. I'm assuming my threads do a
    mcc_thread_delete() just before returning. OR should I build other
    mechanisms, outside mcc to tell me.
    
    I found your discussion very helpful and its pricked my curiousity.
    You mentioned the use of some routines I can't find documentation for
    in the SRM. Specifically mcc_context_xxx() and mcc_cond_wait() and
    mcc_cond_signal(). Are these real? Any more goodies?
    
    
    dave