A standard C18 compiler (with thread and safety support) is required. For the more details, see the library headers.
Do not build the below files directly, which are a private header and a template. Just put them in the same folder with the above files.
For the more detailed example, see this #.
// assign null, specifying it needs to be allocated
thrp_qu *Qu = NULL;
// allocate 1KB with the default allocater
int Flag = ThrP.Qu.Create_( ThrP.UM, NULL, &Qu, 1024 );
// handle the possible error, e.g.
// if( Flag == ThrP.Flag->Success ); else return EXIT_FAILURE;
/* do your job... */
// wait for all tasks to be processed
Flag = ThrP.Qu.Wait_( &Qu );
/* handle the possible error */
// deallocate the space
Flag = ThrP.Qu.Delete_( &Qu );
/* handle the possible error */
// enqueue a user task A into the queue A
Flag = ThrP.Qu.Push_( &QuA, User_Func_A_, sizeof( UserArgA ), &UserArgA );
/* handle the possible error */
// enqueue a user task B into the queue B
Flag = ThrP.Qu.Push_( &QuB, User_Func_B_, sizeof( UserArgB ), &UserArgB );
/* handle the possible error */
// synchronize the queues
Flag = ThrP.Qu.Wait_( &QuA );
/* handle the possible error */
Flag = ThrP.Qu.Wait_( &QuB );
/* handle the possible error */
// assign null, specifying it needs to be allocated
thrp_mu *Mu = NULL;
// allocate the space with the default allocater
int Flag = ThrP.Mu.Create_( ThrP.UM, NULL, &Mu );
// handle the possible error, e.g.
// if( Flag == ThrP.Flag->Success ); else return EXIT_FAILURE;
/* do your job... */
// deallocate the space
Flag = ThrP.Mu.Delete_( &Mu );
/* handle the possible error */
// wait and lock
Flag = ThrP.Mu.Take_( &Mu, true );
/* handle the possible error */
// mutate the state
UserObj->Num++;
// unlock without waiting
Flag = ThrP.Mu.Give_( &Mu, false );
/* handle the possible error */
Or just simply, with an abusive macro #
// wait, lock, do, unlock
ThrP_Mu_Lock_Do_( Flag, &Mu )
UserObj->Num++;