From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

thread ID vs. thread function ID

Solved!
Go to solution

Hi,

 

I am afraid that I do not really understand the difference of a thread ID and a thread function ID, or phrased differently, what is the purpose of the thread ID and why are both needed?

For example, using  CmtScheduleThreadPoolFunction returns a thread function ID, that can be used later on to obtain a thread ID.

 

For function calls such as PostDeferredCallToThread, the thread ID is required, which can be obtained only for the current thread via CmtGetCurrentThreadID, otherwise, one needs to know the thread function ID to obtain the thread ID... seems somewhat complicated

- why can't one use only the thread function ID?

Thank you in advance for explanations...

Wolfgang

Message 1 of 10
(6,960 Views)

The CVI multithreading functions in the Utility library are based on thread pools. Basically, the user creates pools of threads and schedules tasks (functions) to be executed in the different pools. The user does not directly deal with threads. The library manages the threads in a pool and when a thread is free, it uses the thread to execute the task scheduled in that pool. The thread ID is similar to a process ID (PID) and is a unique OS-wide identifier of a thread. The thread function ID is always specific to a CVI thread pool and identifies a task (function) scheduled in the thread pool. The thread function ID is meaningless outside the context of the CVI multithreading library. The thread ID is meaningful in the entire OS. PostDeferredCallToThread uses thread ID because it is a User Interface library function that is independent of the CVI multithreading library.

 

Thread IDs can be obtained in many ways other than just CmtGetCurrentThreadID. For example, CmtGetThreadPoolFunctionAttribute. Also, other libraries may expose thread IDs in various ways - for example, the Windows SDK CreateThread function returns the ID of the created thread. You can easily enough write a PostDeferredCallToThreadFunction kind of function as follows:

 

#include <toolbox.h>

 

static volatile int quit;

 

static int PostDeferredCallToThreadFunction(int pool, int threadFuncId,
 DeferredCallbackPtr deferredFunc)
{
 int error, execStatus, threadId;
 
 errChk(CmtGetThreadPoolFunctionAttribute(pool, threadFuncId,
  ATTR_TP_FUNCTION_EXECUTION_STATUS, &execStatus));
 if (execStatus != kCmtThreadFunctionExecuting)
  errChk(kCmtInvalidParameter);
 errChk(CmtGetThreadPoolFunctionAttribute(pool, threadFuncId,
  ATTR_TP_FUNCTION_THREAD_ID, &threadId));
 errChk(PostDeferredCallToThread(deferredFunc, NULL, threadId));
 
Error:
 return error;
}

 

static void CVICALLBACK DeferredFunction(void *callbackData)
{
 puts( "Deferred function" );
}

 

static int CVICALLBACK ThreadFunction(void *functionData)
{
 while (!quit)
  ProcessSystemEvents();
 return 0;
}

 

void main(void)
{
 int pool, threadFuncId;
 
 CmtNewThreadPool(2, &pool);
 CmtScheduleThreadPoolFunction(pool, ThreadFunction, NULL, &threadFuncId);
 Delay(1.0);
 PostDeferredCallToThreadFunction(pool, threadFuncId, DeferredFunction);
 quit = 1;
 CmtDiscardThreadPool(pool);
 getchar();
}

 

Message Edited by Mohan on 04-24-2009 10:24 AM
Message 2 of 10
(6,941 Views)

Thank you very much!

 

This shed some light on it... What happens if a task has finished, and a new task is scheduled: will the thread function ID be reused, or are thread function IDs incremented continuously?

 

Wolfgang

0 Kudos
Message 3 of 10
(6,935 Views)

The Win32 Theread ID is a global value that uniquely refers to the thread from any process in the system.  At any one instant in time, each active thread has a unique ID.

 

Since it's a DWORD, there can be up to 0xffffffff  = 4,294,967,295 Thread ID's, assuming windows uses the full range.   0 is an invalid Thread ID.

 

The thread ID is valid from the time the thread is created until it terminates.

 

So while as a practical matter it may not get re-used, it's likely poor practice to depend upon a specific thread ID designating a specific instance of a thread.  The referent thread may terminate, and the thread ID get assigned to some other thread.

 

Thread ID's are used in some Win32 SDK calls, like PostThreadMessage() to get to the thread's message queue.

 

The thread ID is different from the thread handle, which is a local process object that other processes cannot easily use.

 

So I think the  sense of a thread ID is for the creating thread (which gets the thread ID from CreateThread function) or the thread itself (GetCurrentThreadID( ) ), or any thread that they give the ID to, to use the ID only in the context where, by design, it is known that the ID is valid.

 

ISBN 0-201-44234-5  is a good reference for Win32 threading.

 

Menchar

 

0 Kudos
Message 4 of 10
(6,927 Views)

Hi Menchar, my question was on the thread function ID - which is CVI specific - and not on the thread ID (OS specific) you were referring to... Other than that, thank you 🙂

 

Wolfgang

 

...if my confusion will increase instead of decrease, I will happily consider having a look at your suggested book - but I hope that I will manage without and be able to remain on the CVI level... - but thank you for this reference!

0 Kudos
Message 5 of 10
(6,923 Views)

Silly me, yes, you were referring to the CVI library's thread  function ID.

 

Menchar

0 Kudos
Message 6 of 10
(6,920 Views)

Wolfgang,

 

It had helped me to visualize the threads and thread functions as workers and work packages, when I first tried to write my MT application.

 

Each worker has its own id, like the badge id of workers in a facility.

There are also id's for each work package a worker is assigned to.

 

First you create a pool of threads, and then make them work on your work package (that is your thread function).

Looking from the point of view this analogy the names of the MT library functions and their purposes may seem more meaningful.

 

Have a nice day, 

S. Eren BALCI
IMESTEK
Message 7 of 10
(6,891 Views)

Thank you,

 

this seems to be a useful picture: The company (thread pool) employs up to a certain amount of employees (thread functions). Indeed, to answer my question on thread function IDs, the thread function IDs are re-used, that is, if one thread function finishes and a new one is scheduled, it will get the same ID - contrary to the thread IDs.

Thanks to all for assistance in this matter,

Wolfgang

0 Kudos
Message 8 of 10
(6,875 Views)
Thread function IDs are NOT reused within a particular pool until CmtReleaseThreadPoolFunctionID is called. Each task (instance of CmtScheduleThreadPoolFunction* call) gets an ID that is unique within its pool. This ID is not reused by the pool until explicitly discarded because the user may query about the status of a task any time during its existence.
Message Edited by Mohan on 04-27-2009 10:47 AM
Message Edited by Mohan on 04-27-2009 10:49 AM
0 Kudos
Message 9 of 10
(6,838 Views)
Solution
Accepted by topic author Wolfgang

I think the analogy works, but Wolfgang's use of "thread function ID" is a little mixed up:

 

employee == thread (has a thread ID)

task == thread function (has thread function ID)

 

The thread pool keeps an idling bunch of threads that sit around waiting for a job to do (thread function scheduled). When a thread finishes its task, it is not destroyed; it just goes back into an idle state waiting for more work. For this reason, it makes sense that thread IDs persist. On the other hand, if the same function is scheduled to run multiple times, each time it runs, it will have a new thread function ID. A thread function ID represents a particular instance of running a function on a thread pool thread.

 

Mert A.

National Instruments

Message 10 of 10
(6,825 Views)