Code: Select all
tag when posting logs, code
Code: Select all
tag when posting logs, code
Code: Select all
An important constraint of the Tcl threads implementation is that only the thread that created a Tcl interpreter can use that interpreter. In other words, multiple threads can not access the same Tcl interpreter. (However, a single thread can safely create and use multiple interpreters.)
Code: Select all
/* mymodule.c */
static void TclCommandQueueHook()
{
CheckTclCommandQueue();
}
char* mymodule_start(Function* global_funcs)
{
/* ... */
InitTclCommandQueue();
add_hook (HOOK_SECONDLY, (Function)TclCommandQueueHook);
/* ... */
}
Code: Select all
/* cmdqueue.h */
#ifdef __cplusplus
extern "C"
{
#endif
int InitTclCommandQueue();
void DispatchTclCommand( const char* aCommand );
void CheckTclCommandQueue();
#ifdef __cplusplus
}
#endif
Code: Select all
/* cmdqueue.c */
struct CmdQueueEntry
{
char* Command;
struct CmdQueueEntry* Next;
};
struct CmdQueueEntry* CmdQueueStart = NULL;
struct CmdQueueEntry* CmdQueueEnd = NULL;
/* mutex for the command queue */
pthread_mutex_t* TclCommandQueueGuard = NULL;
int InitTclCommandQueue()
{
pthread_mutexattr_t aMutexAttribute;
pthread_mutexattr_init( &aMutexAttribute );
pthread_mutexattr_setpshared( &aMutexAttribute, 0 );
pthread_mutexattr_settype( &aMutexAttribute, PTHREAD_MUTEX_RECURSIVE );
// initialize mutex
TclCommandQueueGuard = nmalloc(sizeof( pthread_mutex_t ));
if (pthread_mutex_init( TclCommandQueueGuard, &aMutexAttribute ) != 0)
{
TclCommandQueueGuard = NULL;
return -1;
}
return 0;
}
void DispatchTclCommand( const char* aCommand )
{
if (TclCommandQueueGuard == NULL) return;
pthread_mutex_lock( TclCommandQueueGuard );
{
struct CmdQueueEntry* aNewCommand = nmalloc( sizeof( struct CmdQueueEntry ) );
aNewCommand->Command = nmalloc( strlen( aCommand ) + 1 );
strncpy( aNewCommand->Command, aCommand, strlen(aCommand) );
aNewCommand->Command[strlen( aCommand )] = '\0';
aNewCommand->Next = NULL;
// no end set yet?
if (CmdQueueEnd == NULL)
{
// start from the beginning
struct CmdQueueEntry* Next = CmdQueueStart;
if (Next != NULL)
{
while (Next->Next != NULL)
{
Next = Next->Next;
}
CmdQueueEnd = Next;
}
// no start yet?
else
{
CmdQueueStart = aNewCommand;
CmdQueueEnd = aNewCommand;
}
}
else
{
CmdQueueEnd->Next = aNewCommand;
CmdQueueEnd = aNewCommand;
}
}
pthread_mutex_unlock( TclCommandQueueGuard );
}
void CheckTclCommandQueue()
{
if (TclCommandQueueGuard == NULL) return;
pthread_mutex_lock( TclCommandQueueGuard );
{
while (CmdQueueStart != NULL)
{
if (CmdQueueStart->Command != NULL)
{
Tcl_EvalEx( interp, CmdQueueStart->Command, -1, TCL_EVAL_GLOBAL );
nfree( CmdQueueStart->Command );
}
struct CmdQueueEntry* Next = CmdQueueStart->Next;
nfree( CmdQueueStart );
CmdQueueStart = Next;
}
CmdQueueEnd = CmdQueueStart;
}
pthread_mutex_unlock( TclCommandQueueGuard );
}
I'd care if your efforts serve a purpose other than exercising your MT skills - that is, an eggdrop purpose (and you are able to demonstrate how eggdrop benefits from that)Kappa007 wrote: Ohh just by the way here's the code I currently use to dispatch Tcl commands (just in case anyone cares).
Code: Select all
tag when posting logs, code
Did you read my post? Its absoludly possible to run asyncron tasks. Btw. the reason eggdrop is so popular is, because its single threaded. That way shells can restrict eggdrop shells to 1 bg process. For further background tasks possible. Furthermore 1 bg process eggdrop = 1 IRC connection. For hosting on a general shell account with multiple back processes and connections allowed it might be usefull, but that wouldnt be all. Eggdrop is and will always keep single threaded and single server for these reasons. You can however still fork into a forground thread to execute async calls as mentioned above by me.Kappa007 wrote:Well benefits are: you can use (foreign) code which uses blocking calls in your modules w/o having to worry about your eggdrop beeing stalled.
And that's enough for me
well, you're still on the proof-of-concept stageKappa007 wrote:Well benefits are: you can use (foreign) code which uses blocking calls in your modules w/o having to worry about your eggdrop beeing stalled.
And that's enough for me
And if that does not count for you then it's just about the possibility to use them at all
Code: Select all
tag when posting logs, code