int main( int argc, char *argv[]) { int key; ULONG ulMode; const char *modeName[] = {"DART", "UNIAUD"}; KAICAPS kaic; TID tid1, tid2, tid3; ulMode = ( argc < 2 ) ? KAIM_AUTO : atoi( argv[ 1 ]); if( kaiInit( ulMode )) { fprintf( stderr, "Failed to init kai\n"); return 0; } kaiCaps( &kaic ); printf("Mode = %s, Available channels = %ld, PDD Name = %s\n", modeName[ kaic.ulMode - 1 ], kaic.ulMaxChannels, kaic.szPDDName ); printf("Press ESC to quit\n"); m_fQuit = FALSE; m_nThreads = 0; tid1 = play("demo1.wav"); tid2 = play("demo2.wav"); tid3 = play("demo3.wav"); while( !m_fQuit && m_nThreads ) { key = read_key(); if( key == 27 ) /* ESC */ m_fQuit = TRUE; DosSleep( 1 ); } DosWaitThread( &tid1, DCWW_WAIT ); DosWaitThread( &tid2, DCWW_WAIT ); DosWaitThread( &tid3, DCWW_WAIT ); kaiDone(); return 0; }
/** * Cleans up after system_Init() and system_Configure(). */ void system_End(void) { if( tidIPCFirst == _gettid()) { HPIPE hpipe; ULONG ulAction; ULONG cbActual; ULONG rc; do { rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_FAIL_ON_ERROR, NULL ); if( rc == ERROR_PIPE_BUSY ) DosWaitNPipe( VLC_IPC_PIPE, -1 ); else if( rc ) DosSleep( 1 ); } while( rc ); /* Ask for IPCHelper to quit */ ULONG ulCmd = IPC_CMD_QUIT; DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual ); DosClose( hpipe ); TID tid = tidIPCHelper; DosWaitThread( &tid, DCWW_WAIT ); } }
void omni_thread::join(void** status) { mutex.lock(); if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { mutex.unlock(); throw omni_thread_invalid(); } mutex.unlock(); if (this == self()) throw omni_thread_invalid(); if (detached) throw omni_thread_invalid(); DB(cerr << "omni_thread::join: doing DosWaitThread\n"); APIRET rc = DosWaitThread( &handle , DCWW_WAIT ); if ( rc != 0 ) throw omni_thread_fatal(rc); DB(cerr << "omni_thread::join: DosWaitThread succeeded\n"); if (status) *status = return_val; delete this; }
/*-------------------------------------------------- * Wait the thread *-------------------------------------------------*/ PMThread& PMThread::join() { if( run_id != -1 ) DosWaitThread( &run_id, DCWW_WAIT ); return *this; }
/****************************************************************\ * Routine to signal consumer to release resource. * *--------------------------------------------------------------* * * * Name: SignalUserEvent(pfAutoMode) * * * * Purpose: Posts user event semaphore to signal thread to * * release resource. Also posts event to stop * * Auto mode if *pfAutoMode is true. * * * * Usage: Called in file usercmd.c when the user selects * * Event from the semaphore menu. * * * * Method: Turns off Auto mode, if present by posting auto * * semaphore. User event is then posted. * * * * Returns: * * * \****************************************************************/ VOID SignalUserEvent(PULONG pfAutoMode) { ULONG rc; /* If sample is in auto mode turn auto mode off. */ if (*pfAutoMode) { rc = DosPostEventSem(hevStopAuto); if (rc) { SemError("DosPostEventSem Stop Auto",rc); } /* Wait for auto mode thread to die, so we don't end up with multiple copies of it later. */ rc = DosWaitThread(&tidAutoThread,0L); if (rc) { SemError("DosWaitThread",rc); } *pfAutoMode = FALSE; DosCloseEventSem (hevStopAuto); } /* If Auto mode haas already posted the event this is OK so we will not check error codes here. */ DosPostEventSem(aSquares[rand() % MAXRESOURCES].hev); return; }
int main(void) { APIRET apiret; TID tid; HEV hev; int i; /* test thread1 */ printf(__FILE__ " main function invoked\n"); printf("Test named event semaphores\n"); apiret = DosCreateEventSem("\\SEM32\\TEST3SEM", &hev, DC_SEM_SHARED, FALSE); printf("DosCreateEventSem function returned %d\n", (int)apiret); /* post to thread 1 */ printf("Starting thread with DosCreateThread\n"); apiret = DosCreateThread(&tid, thread1, (ULONG)hev, 0, 8092); for (i = 0; i < 4; i++) { apiret = DosPostEventSem(hev); printf("Function DosPostEventSem returned %d\n", (int)apiret); DosSleep(1500); /* 1.5 seconds */ } apiret = DosWaitThread(&tid, DCWW_WAIT); printf("Function DosWaitThread returned %d\n", (int)apiret); /* post to thread 2 */ printf("Starting thread with DosCreateThread\n"); apiret = DosCreateThread(&tid, thread2, (ULONG)hev, 0, 8092); for (i = 0; i < 4; i++) { apiret = DosPostEventSem(hev); printf("Function DosPostEventSem returned %d\n", (int)apiret); DosSleep(1500); /* 1.5 seconds */ } apiret = DosWaitThread(&tid, DCWW_WAIT); printf("Function DosWaitThread returned %d\n", (int)apiret); printf("The last DosWaitEventSem should have returned 640\n"); apiret = DosCloseEventSem(hev); printf("Function DosCloseEventSem returned %d\n", (int)apiret); return 0; }
/****************************************************************\ * Routine to really stop semaphore example. * *--------------------------------------------------------------* * * * Name: StopSemaphore( PVOID pvArg ) * * * * Purpose: Waits for threads to complete, * * Sends message to message thread to indicate this * * has occurred, and exits. * * * * Usage: Exec'd from BeginStop when user selects Stop from * * Semaphore menu. * * * * Method: Turns off Auto mode, if present by posting auto * * semaphore. Then stop event is posted. Waits * * for threads to die. * * Returns: * * * \****************************************************************/ VOID StopSemaphore( PVOID pvArg ) { ULONG rc,usCount, i; PULONG pfAutoMode = (PULONG)pvArg; if (*pfAutoMode) { rc = DosWaitThread(&tidAutoThread,0L); if (rc && (rc != ERROR_INVALID_THREADID)) { SemError("DosWaitThread",rc); } *pfAutoMode = FALSE; } /* Wait for usConsumer threads to die. Order of death not important. */ for (usCount = 0; usCount < usConsumerThreadsCreated; usCount++) { rc = DosWaitThread(&thrConsumers[usCount].tid,0L); /* rc is ERROR_INVALID_THREADID the thread is already dead.*\ \* This is OK and not a error. */ if (rc && (rc != ERROR_INVALID_THREADID)) { SemError("DosWaitThread",rc); } } /* Threads dead so we don't need semaphores any more. */ DosCloseEventSem(hevStopAuto); DosCloseEventSem(hevStop); DosCloseMutexSem(hmtxOwnResource); for (i = 0; i < MAXRESOURCES; i++) { DosCloseEventSem(aSquares[i].hev); } DosCloseMuxWaitSem (hmuxResource); WinPostMsg (hwndMain, WM_COMMAND, (MPARAM)IDM_STOPFINISHED, (MPARAM)NULL); DosExit (EXIT_THREAD, 0); return; }
int main( void ) { TID tid; tid = _beginthread( worker, NULL, 1024 * 1024, NULL ); DosWaitThread( &tid, DCWW_WAIT ); worker( NULL ); return 0; }
void vlc_timer_destroy (vlc_timer_t timer) { if (timer->htimer != NULLHANDLE) DosStopTimer (timer->htimer); timer->quit = true; DosPostEventSem (timer->hev); DosWaitThread (&timer->tid, DCWW_WAIT); DosCloseEventSem (timer->hev); free (timer); }
SSMODULEDECLSPEC int SSMODULECALL SSModule_StopSaving(void) { // This is called when we have to stop saving. #ifdef DEBUG_LOGGING AddLog("[SSModule_StopSaving] : Enter!\n"); #endif if (!bRunning) { #ifdef DEBUG_LOGGING AddLog("[SSModule_StopSaving] : Not running, Leaving.\n"); #endif return SSMODULE_ERROR_NOTRUNNING; } #ifdef DEBUG_LOGGING AddLog("[SSModule_StopSaving] : Closing saver window\n"); #endif // Notify saver thread to stop! if (bOnlyPreviewMode) { // In preview mode, which means that there is no window created, but the // window was subclassed. So we cannot close the window, but we have to // post the WM_QUIT message into the thread's message queue to notify it // that this is the end of its job. WinPostQueueMsg(hmqSaverThreadMsgQueue, WM_QUIT, (MPARAM) NULL, (MPARAM) NULL); } else { // Close saver window WinPostMsg(hwndSaverWindow, WM_QUIT, (MPARAM) NULL, (MPARAM) NULL); } #ifdef DEBUG_LOGGING AddLog("[SSModule_StopSaving] : Waiting for thread to die\n"); #endif // Wait for the thread to stop DosWaitThread(&tidSaverThread, DCWW_WAIT); #ifdef DEBUG_LOGGING AddLog("[SSModule_StopSaving] : Screen saver stopped.\n"); #endif // Ok, screensaver stopped. bRunning = FALSE; free(CfgDlgInit.pchText); CfgDlgInit.pchText = NULL; return SSMODULE_NOERROR; }
// ------------------------------------------------------------------------------------------------------------ int main( int argc, char **argv ) { HMQ hmq; QMSG qmsg; ULONG ulWork; SWP swp; LONG cx; // initialize globals struct to defaults memset( &globals, 0, sizeof( globals )); strcpy( globals.szRexxFileName, "DRAW.CMD" ); // parameter is a REXX filename if( argc > 1 ) { strcpy( globals.szRexxFileName, argv[ 1 ] ); } // PM application init globals.hab = WinInitialize( 0 ); hmq = WinCreateMsgQueue( globals.hab, 0); // create a frame window with listbox to display REXX diagnostic output ulWork = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_ICON | FCF_TASKLIST; globals.hwndOutputFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWork, WC_LISTBOX, OUTPUTCAPTION, LS_NOADJUSTPOS, (HMODULE)0, ID_RXDRAW, &globals.hwndOutputListbox ); assert( globals.hwndOutputFrame ); assert( globals.hwndOutputListbox ); // create a frame window to display REXX graphical output WinRegisterClass( globals.hab, CLASSNAME, (PFNWP)ClientWinProc, CS_SIZEREDRAW, 0 ); ulWork = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_MENU | FCF_ICON | FCF_TASKLIST; globals.hwndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWork, CLASSNAME, CAPTION, 0, (HMODULE)0, ID_RXDRAW, &globals.hwndClient ); assert( globals.hwndFrame ); assert( globals.hwndClient ); // tile the two windows using shell's preferred placement for one WinQueryTaskSizePos( globals.hab, 0, &swp ); cx = (swp.cx * 2) / 3; ulWork = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE | SWP_RESTORE; WinSetWindowPos( globals.hwndOutputFrame, HWND_TOP, swp.x+cx, swp.y, swp.cx-cx, swp.cy, ulWork ); WinSetWindowPos( globals.hwndFrame, HWND_TOP, swp.x, swp.y, cx, swp.cy, ulWork ); // message loop while( WinGetMsg( globals.hab, &qmsg, 0, 0, 0 )) WinDispatchMsg( globals.hab, &qmsg ); if( !globals.fCloseMsgSent ) { // got a WM_QUIT without WM_CLOSE; must be shutdown or Close from Window List WinPostMsg( globals.hwndObject, WM_QUIT, 0, 0 ); } // clean up WinDestroyWindow( globals.hwndFrame ); WinDestroyWindow( globals.hwndOutputFrame ); WinDestroyMsgQueue( hmq ); WinTerminate( globals.hab ); DosWaitThread( &globals.tidObject, DCWW_WAIT ); return 0; }
void TThreads::suspend() { shutDownFlag=1; TID localTID=mouseThreadID; if (localTID != 0xFFFF) DosWaitThread(&localTID,DCWW_WAIT); // cerr << " MouseThread has ended\n"; ULONG count; assert(! DosQueryEventSem(TThreads::hevKeyboard2,&count)); if (!count) assert(! DosPostEventSem(TThreads::hevKeyboard2)); // Make sure the thread is running. localTID=keyboardThreadID; DosWaitThread(&localTID,DCWW_WAIT); // cerr << " KeyboardThread has ended\n"; assert(!DosCloseMutexSem(hmtxMouse1)); assert(!DosCloseEventSem(hevKeyboard2)); assert(!DosCloseEventSem(hevKeyboard1)); assert(!DosCloseEventSem(hevMouse2)); assert(!DosCloseEventSem(hevMouse1)); assert(!DosCloseMuxWaitSem(hmuxMaster)); if (tiled->mouseHandle != 0xFFFF) MouClose(tiled->mouseHandle); // This doesn't work, the mouseThread uses the handle. assert(! DosFreeMem(tiled)); // Better not, dito }
/***************************************************************************** * Close: destroy KVA video thread output method ***************************************************************************** * Terminate an output method created by Open *****************************************************************************/ static void Close ( vlc_object_t *object ) { vout_display_t * vd = (vout_display_t *)object; vout_display_sys_t * sys = vd->sys; WinPostQueueMsg( sys->hmq, WM_QUIT, 0, 0 ); DosWaitThread( &sys->tid, DCWW_WAIT ); if( sys->pool ) picture_pool_Delete( sys->pool ); DosCloseEventSem( sys->ack_event ); free( sys ); }
SilcBool silc_thread_wait(SilcThread thread, void **exit_value) { #ifdef SILC_THREADS if (DosWaitThread((unsigned long)thread, DCWW_WAIT) != ERROR_INVALID_THREADID) { if (exit_value) *exit_value = NULL; return TRUE; } return FALSE; #else return FALSE; #endif }
/******************************************************************************* Timeout waiting for a thread to terminate. Alarms if unsucessful. *******************************************************************************/ BOOL TimeoutDlgThread(PTID pTid, ULONG ulNtimeslices) { APIRET rc; do { rc = DosWaitThread(pTid, DCWW_NOWAIT); if(rc == ERROR_THREAD_NOT_TERMINATED) { DosSleep(1); ulNtimeslices--; } else if(rc == NO_ERROR) return(TRUE); else return(FALSE); } while(ulNtimeslices); if(!ulNtimeslices) WinAlarm(HWND_DESKTOP, WA_ERROR); return(FALSE); }
/** * free what has been allocated by avcodec_thread_init(). * must be called after decoding has finished, especially do not call while avcodec_thread_execute() is running */ void avcodec_thread_free(AVCodecContext *s){ ThreadContext *c= s->thread_opaque; int i; for(i=0; i<s->thread_count; i++){ c[i].func= NULL; DosPostEventSem(c[i].work_sem); // ReleaseSemaphore(c[i].work_sem, 1, 0); DosWaitThread((PTID)&c[i].thread,DCWW_WAIT); // WaitForSingleObject(c[i].thread, INFINITE); if(c[i].work_sem) DosCloseEventSem(c[i].work_sem);//CloseHandle(c[i].work_sem); if(c[i].done_sem) DosCloseEventSem(c[i].done_sem);//CloseHandle(c[i].done_sem); } av_freep(&s->thread_opaque); }
SSMODULEDECLSPEC int SSMODULECALL SSModule_StartSaving(HWND hwndParent, char *pchHomeDirectory, int bPreviewMode) { // This is called when we should start the saving. // Return error if already running, start the saver thread otherwise! if (bRunning) return SSMODULE_ERROR_ALREADYRUNNING; readConfig(pchHomeDirectory); iSaverThreadState = STATE_UNKNOWN; bOnlyPreviewMode = bPreviewMode; tidSaverThread = _beginthread(fnSaverThread, 0, 1024*1024, (void *) hwndParent); if (tidSaverThread == 0) { #ifdef DEBUG_LOGGING AddLog("[SSModule_StartSaving] : Error creating screensaver thread!\n"); #endif // Error creating screensaver thread! return SSMODULE_ERROR_INTERNALERROR; } // Wait for saver thread to start up! while (iSaverThreadState==STATE_UNKNOWN) DosSleep(32); if (iSaverThreadState!=STATE_RUNNING) { #ifdef DEBUG_LOGGING AddLog("[SSModule_StartSaving] : Something went wrong in screensaver thread!\n"); #endif // Something wrong in saver thread! DosWaitThread(&tidSaverThread, DCWW_WAIT); return SSMODULE_ERROR_INTERNALERROR; } // Fine, screen saver started and running! bRunning = TRUE; return SSMODULE_NOERROR; }
/* wait for all benchmark threads to terminate */ void WaitForThreads(ThreadID tids[], unsigned tidCnt) { #ifdef __OS2__ while (tidCnt--) DosWaitThread(&tids[tidCnt], DCWW_WAIT); #elif defined(WIN32) WaitForMultipleObjects(tidCnt, tids, TRUE, INFINITE); #elif defined(__sun) int prio; thr_getprio(thr_self(), &prio); thr_setprio(thr_self(), max(0, prio-1)); while (tidCnt--) thr_join(0, NULL, NULL); #elif defined(_POSIX_THREADS) || defined(_POSIX_REENTRANT_FUNCTIONS) while (tidCnt--) pthread_join(tids[tidCnt], NULL); #endif }
int GUI::ClosePipe(int id) { if ((id < 0) || (id > MAX_PIPES)) return -1; if (Pipes[id].used == 0) return -1; if (Pipes[id].reading == 1) { Pipes[id].DoTerm = 1; DosPostEventSem(Pipes[id].ResumeRead); DosWaitThread(&Pipes[id].tid, DCWW_WAIT); } free(Pipes[id].buffer); free(Pipes[id].Command); DosCloseEventSem(Pipes[id].NewData); DosCloseEventSem(Pipes[id].ResumeRead); DosCloseMutexSem(Pipes[id].Access); // fprintf(stderr, "Pipe Close: %d\n", id); Pipes[id].used = 0; // ConContinue(); return Pipes[id].RetCode; }
int bd_rix(void) { void BuildFieldListRix(FIELDDESCTYPE fieldList[]); #pragma pack(1) ACCESSPACK AP; DOSFILEPACK DFP; CREATEDATAPACK CDP; CREATEINDEXPACK CIP; HANDLEPACK HP; OPENPACK OP; QUERYSETPACK QSP; STATINDEXPACK SIP; // for separate thread reindex percentage done struct EmpRecType { CHAR tag; // record tag, init to SPACE, * means deleted CHAR empID[9]; // SSN (not 0T string) CHAR empLN[16]; // last name CHAR empFN[16]; // first name CHAR empHire[8]; // "YYYYMMDD" (not 0T string) CHAR empDept[6]; // department assigned }; // 56 bytes struct EmpRecType EmpRec; #pragma pack() // no more Bullet-accessed data structures follow time_t startTime, endTime; int display = 0; // display results or not flag int thread = 1; // dispatch reindex in a thread flag int lastNameVar; // used to construct on-the-fly data record... int lastFourVar; // ...that is unique LONG rez; // return value from Bullet CHAR nameIX3[] = ".\\$bd_rix.ix3"; // name of index file created ULONG indexID=0; // handle of index file CHAR keyExpression[128]; // key expression string buffer (159 max) CHAR keyBuffer[68]; // buffer used to store/receive key values CHAR nameData[] = ".\\$bd_rix.dbf";// name of data file created ULONG dataID=0; // handle of data file FIELDDESCTYPE fieldList[5]; // 5 fields used in data record LONG i; // counter CHAR tmpStr[128]; // misc stuff, non-Bullet related CHAR putStr[128]; ULONG tmpU; SIP.func = 0; // init+ref it for DOSX32 compile // set field descriptor info for DBF data file created later memset(fieldList,0,sizeof(fieldList)); // init unused bytes to 0 (required) BuildFieldListRix(fieldList); // Use 300K for workspace in reindex module (min is 48K, max is whatever you want) // Note: larger is not necessarily faster; it depends on the data order #define NEW_XBUFF_SIZE (300*1024) QSP.func = SET_SYSVARS_XB; QSP.item = REINDEX_BUFFER_SIZE; QSP.itemValue = NEW_XBUFF_SIZE; rez = BULLET(&QSP); if (rez) { sprintf(putStr,"Failed SET_SYSVARS_XB #%d (reindex buffer size) call. Err: %d\n",QSP.item,rez); PutMsg(putStr); goto Abend; } tmpU = QSP.itemValue; // 0=default, or 144KB total buffer space if (tmpU == 0) tmpU = (144*1024); sprintf(putStr,"Bullet reindex tmp buffer was %d KB, now %d KB\n", tmpU/1024, NEW_XBUFF_SIZE/1024); PutMsg(putStr); // Delete previous files from any previous run (disregard any error return) DFP.func = DELETE_FILE_DOS; DFP.filenamePtr = nameData; rez = BULLET(&DFP); DFP.filenamePtr = nameIX3; rez = BULLET(&DFP); // Create the data file, a standard DBF (ID=3) as defined in fieldList above. CDP.func = CREATE_DATA_XB; CDP.filenamePtr = nameData; CDP.noFields = 5; CDP.fieldListPtr = fieldList; CDP.fileID = 0x03; rez = BULLET(&CDP); if (rez) { sprintf(putStr,"Failed data file create. Err: %d\n",rez); PutMsg(putStr); goto Abend; } // Open the data file (required before creating an index file for it) OP.func = OPEN_DATA_XB; OP.filenamePtr = nameData; OP.asMode = READWRITE | DENYNONE; rez = BULLET(&OP); if (rez) { sprintf(putStr,"Failed data file open. Err: %d\n",rez); PutMsg(putStr); goto Abend; } dataID = OP.handle; // Create an index file for the data file opened above. // This example uses a multi-part key composed of parts of last name and SSN. strcpy(keyExpression,"SUBSTR(LNAME,1,4)+SUBSTR(SSN,6,4)"); CIP.func = CREATE_INDEX_XB; CIP.filenamePtr = nameIX3; CIP.keyExpPtr = keyExpression; CIP.xbLink = dataID; // the handle of the data file CIP.sortFunction = NLS_SORT | SORT_SET; // sort by NLS (SORT_SET defined in PLATFORM.H) CIP.codePage = CODEPAGE; // code page to use, or 0 for system default CIP.countryCode = CTRYCODE; // country code... CIP.collatePtr = collateTable; // (see #define INT2165xxNS above) CIP.nodeSize = 512; // 512-byte node size (or 1024, 2048 bytes) rez = BULLET(&CIP); if (rez) { sprintf(putStr,"Failed index file create. Err: %d\n",rez); PutMsg(putStr); goto Abend; } // Open the index file (what we just created above). // As with the index-create, the index-open requires the handle of the data // file which this index file indexes. OP.func = OPEN_INDEX_XB; OP.filenamePtr = nameIX3; OP.asMode = READWRITE | DENYNONE; OP.xbLink = dataID; rez = BULLET(&OP); if (rez) { sprintf(putStr,"Failed index file open. Err: %d\n",rez); PutMsg(putStr); goto Abend; } indexID = OP.handle; PutMsg("Display all data accessed (slower results)? (y/N) "); GetMsg(tmpStr); if (*tmpStr=='y') display = 1; #if PLATFORM == ON_OS2 || PLATFORM == ON_WIN32 && FOR_WINDOWS == 0 PutMsg(" Dispatch REINDEX_XB in a separate thread? (Y/n) "); GetMsg(tmpStr); if (*tmpStr=='n') thread = 0; #else thread = 0; #endif PutMsg(" How many records do you want for this test run? "); GetMsg(tmpStr); recs2add = atol(tmpStr); if (recs2add < 1) recs2add = 1; // would you rather end the test? if (recs2add > 9999999) recs2add = 1; // why wait around for 10M? // Add the data records, which are created here, on-the-fly, varying enough // to make unique records. lastFourVar = 1; // 0001 start (as used in strncpy() below) lastNameVar = 0; // 0000 start EmpRec.tag = ' '; // set to not-deleted strncpy(EmpRec.empID,"465990001",9); // only changing last 4 in test strcpy(EmpRec.empLN,"0000LastNameNum"); // only changing first 4 in test strcpy(EmpRec.empFN,"YourFirstName"); // everyone has this first name! strncpy(EmpRec.empHire,"19950527",8); // YYYYMMDD DBF form, no \0 on date strcpy(EmpRec.empDept,"MIS"); // everyone works for MIS! sprintf(putStr," Adding %d records... ",recs2add); PutMsg(putStr); time(&startTime); AP.func = ADD_RECORD_XB; AP.handle = dataID; AP.recPtr = &EmpRec; for (i = 1; i <= recs2add; i++) { sprintf(tmpStr,"%4.4i",lastFourVar++); strncpy(EmpRec.empID+5,tmpStr,4); // update last 4 of empID rez = BULLET(&AP); // AP. already setup if (rez) { sprintf(putStr,"Failed while adding record %d. Err: %d\n",i,rez); PutMsg(putStr); goto Abend; } if (lastFourVar > 9999) { // changes every 10,000 adds lastFourVar = 0; // where name takes carry ... sprintf(tmpStr,"%4.4i",++lastNameVar); strncpy(EmpRec.empLN,tmpStr,4); // update first 4 of empLN } #if FOR_WINDOWS == 1 // deal with message queue every now and then if (i % Q_ADD == 0) DoWinThing(0); // 0=no waiting around #endif } time(&endTime); sprintf(putStr,"took %u secs.\n",(endTime - startTime)); PutMsg(putStr); // Reindex sprintf(putStr,"Reindexing %d records... \r",recs2add); PutMsg(putStr); time(&startTime); AP.func = REINDEX_XB; // this is all there is to reindexing even... AP.handle = indexID; // ...million-record databases AP.keyPtr = keyBuffer; // if dup key error...(see manual for details) AP.nextPtr = NULL; // just this one index file if (thread) { #if PLATFORM == ON_DOSX32 PutMsg(" Threads are not supported on this OS\n"); goto Abend; #elif PLATFORM == ON_OS2 rez = DosCreateThread(&tidRix, (PFNTHREAD) &ThreadRix, (ULONG) &AP, CREATE_READY | STACK_SPARSE, 32768); // min is 8K stack if (rez) { sprintf(putStr,"Could not start reindex thread. Err: %d\n",rez); PutMsg(putStr); goto Abend; } DosSleep(32); // wait a bit to let reindex code set progress to non-zero // could also use a callback routine to put out a reindex % number SIP.func = STAT_INDEX_XB; SIP.handle = indexID; rez = BULLET(&SIP); while (rez==0) { DosSleep(100); sprintf(putStr,"Reindexing %d records... %3.3u%%\r",recs2add,SIP.progress); PutMsg(putStr); rez = BULLET(&SIP); if (SIP.progress==0) { sprintf(putStr,"Reindexing %d records... ",recs2add); PutMsg(putStr); break; } } if (rez) { sprintf(putStr,"Failed progress check. Err: %d\n",rez); PutMsg(putStr); } // continue // Can actually get here _before_ the reindex thread fully exits, but // won't get here until SIP.progress is back to 0. time(&endTime); // It's likely that the thread has exited completely by now, but if // it was blocked after setting SIP.progress to 0 (hung up in the cache, // etc.), then it's possible to get here well before Bullet has exited. // Since calling Bullet while Bullet is busy (for most routines) results // in a rc=640 being returned (mutex timeout), just call this to wait // for the thread to exit completely. Note that this has only been seen // under Win95 (done, but blocked), but this little routine won't hurt. // Ignore any error, which there will be if the thread has indeed exited. // Another option is to use a non-0 mutex-timeout value, via SET_SYSVARS_XB. rez = DosWaitThread(&tidRix,DCWW_WAIT); // ignore error (such as "invalid thread ID") DosSleep(1); // allow the reindex thread to exit BULLET() (and set rez) rez = rezRix; // get return code set by ThreadRix() if (rez) { // rez is already AP.stat sprintf(putStr,"Failed reindex. Err: %d\n",rez); PutMsg(putStr); goto Abend; } sprintf(putStr,"took %u secs.\n",(endTime - startTime)); PutMsg(putStr); #elif PLATFORM == ON_WIN32 hRix = CreateThread(NULL, 32768, // 8KB min. (LPTHREAD_START_ROUTINE) &ThreadRix, (PACCESSPACK) &AP, 0, // immediate start &tidRix); if (hRix==0) { rez = GetLastError(); sprintf(putStr,"Could not start reindex thread. Err: %d\n",rez); PutMsg(putStr); goto Abend; } Sleep(32); // wait a bit to let reindex code set progress to non-zero SIP.func = STAT_INDEX_XB; SIP.handle = indexID; rez = BULLET(&SIP); while (rez==0) { Sleep(100); sprintf(putStr,"Reindexing %d records... %3.3u%%\r",recs2add,SIP.progress); PutMsg(putStr); rez = BULLET(&SIP); if (SIP.progress==0) { sprintf(putStr,"Reindexing %d records... ",recs2add); PutMsg(putStr); break; } } if (rez) { sprintf(putStr,"Failed progress check. Err: %d\n",rez); PutMsg(putStr); } // continue // Can actually get here _before_ the reindex thread fully exits, but // won't get here until SIP.progress is back to 0. time(&endTime); // It's likely that the thread has exited completely by now, but if // it was blocked after setting SIP.progress to 0 (hung up in the cache, // etc.), then it's possible to get here well before Bullet has exited. // Since calling Bullet while Bullet is busy (for most routines) results // in a rc=640 being returned (mutex timeout), just call this to wait // for the thread to exit completely. Note that this has only been seen // under Win95 (done, but blocked), but this little routine won't hurt. // Ignore any error, which there will be if the thread has indeed exited. // Another option is to use a non-0 mutex-timeout value, via SET_SYSVARS_XB. // Error code 640 is documented in BULLET_2.H. rez = WaitForSingleObject(hRix,10*1000); // 10 secs plenty of flush time // ignore error Sleep(32); // allow the reindex thread to exit BULLET() (and set rez) // why 32ms? Only because OS/2 min std resolution is 32ms rez = rezRix; // get return code set by ThreadRix() if (rez) { // rez is already AP.stat sprintf(putStr,"Failed reindex. Err: %d\n",rez); PutMsg(putStr); goto Abend; } sprintf(putStr,"took %u secs.\n",(endTime - startTime)); PutMsg(putStr); #endif } else { // no separate thread, so use callback (especially useful for DOSX32 and Win32s) QSP.func = SET_SYSVARS_XB; QSP.item = CALLBACK_PTR; QSP.itemValue = (ULONG) &CallbackRix; rez = BULLET(&QSP); if (rez) { sprintf(putStr,"Failed SET_SYSVARS_XB #%d (callback address) call. Err: %d\n",QSP.item,rez); PutMsg(putStr); goto Abend; } // now make actual REINDEX_XB call, set up above rez = BULLET(&AP); // rez=0 if okay, or =1 if pack failed with ecode in AP.stat if (rez) { rez = AP.stat; sprintf(putStr,"Failed reindex. Err: %d\n",rez); PutMsg(putStr); goto Abend; } time(&endTime); sprintf(putStr,"Reindexing %d records... took %u secs.\n",recs2add,(endTime - startTime)); PutMsg(putStr); // turn off callback QSP.func = SET_SYSVARS_XB; QSP.item = CALLBACK_PTR; QSP.itemValue = 0; rez = BULLET(&QSP); if (rez) { sprintf(putStr,"Failed SET_SYSVARS_XB #%d (callback clear) call. Err: %d\n",QSP.item,rez); PutMsg(putStr); goto Abend; } } // Get key data memset(keyBuffer,0,sizeof(keyBuffer)); sprintf(putStr," Accessing %d keys... ",recs2add); PutMsg(putStr); if (display) PutMsg("\n"); time(&startTime); AP.func = FIRST_KEY_XB; AP.handle = indexID; AP.keyPtr = keyBuffer; rez = BULLET(&AP); i=0; while (rez==0) { if (display) { sprintf(putStr,"%s %9.9lu\r", keyBuffer, AP.recNo); PutMsg(putStr); } i++; AP.func = NEXT_KEY_XB; rez = BULLET(&AP); #if FOR_WINDOWS == 1 // deal with message queue every now and then if (i % Q_KEY == 0) DoWinThing(0); // 0=no waiting around #endif } time(&endTime); if (display) PutMsg("\n..."); // expected rez is EXB_END_OF_FILE if (rez == EXB_END_OF_FILE) rez=0; if (rez) { sprintf(putStr,"Failed KEY access. Err: %d\n",rez); PutMsg(putStr); goto Abend; } sprintf(putStr,"took %u secs. for %d keys\n",(endTime - startTime),i); PutMsg(putStr); // Get key and record data sprintf(putStr," Accessing %d keys+recs...",recs2add); PutMsg(putStr); if (display) PutMsg("\n"); time(&startTime); AP.func = GET_FIRST_XB; AP.handle = indexID; AP.keyPtr = keyBuffer; AP.recPtr = &EmpRec; rez = BULLET(&AP); i=0; while (rez==0) { if (display) { sprintf(putStr,"%s %9.9lu %s\r", keyBuffer, AP.recNo, &EmpRec); // partial show PutMsg(putStr); } i++; AP.func = GET_NEXT_XB; rez = BULLET(&AP); #if FOR_WINDOWS == 1 // deal with message queue every now and then if (i % Q_GET == 0) DoWinThing(0); // 0=no waiting around #endif } time(&endTime); if (display) PutMsg("\n..."); // expected rez is EXB_END_OF_FILE if (rez == EXB_END_OF_FILE) rez=0; if (rez) { sprintf(putStr,"Failed GET access. Err: %d\n",rez); PutMsg(putStr); goto Abend; } sprintf(putStr,"took %u secs. for %d keys & records\n",(endTime - startTime),i); PutMsg(putStr); // Fatal errors above come straight to here Abend: // Close files if (indexID) { HP.func = CLOSE_INDEX_XB; HP.handle = indexID; rez = BULLET(&HP); if (rez) { sprintf(putStr,"Failed index file close. Err: %d\n",rez); PutMsg(putStr); } } // Unlikely the above could fail, considering how far it has gotten so far! // But logic says that we want to continue closing other open files... if (dataID) { HP.func = CLOSE_DATA_XB; HP.handle = dataID; rez = BULLET(&HP); if (rez) { sprintf(putStr,"Failed data file close. Err: %d\n",rez); PutMsg(putStr); } } return rez; // module exit }
void ap_mpm_child_main(apr_pool_t *pconf) { ap_listen_rec *lr = NULL; int requests_this_child = 0; int rv = 0; unsigned long ulTimes; int my_pid = getpid(); ULONG rc, c; HQUEUE workq; apr_pollset_t *pollset; int num_listeners; TID server_maint_tid; void *sb_mem; /* Stop Ctrl-C/Ctrl-Break signals going to child processes */ DosSetSignalExceptionFocus(0, &ulTimes); set_signals(); /* Create pool for child */ apr_pool_create(&pchild, pconf); ap_run_child_init(pchild, ap_server_conf); /* Create an event semaphore used to trigger other threads to shutdown */ rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE); if (rc) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, "unable to create shutdown semaphore, exiting"); clean_child_exit(APEXIT_CHILDFATAL); } /* Gain access to the scoreboard. */ rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname, PAG_READ|PAG_WRITE); if (rc) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, "scoreboard not readable in child, exiting"); clean_child_exit(APEXIT_CHILDFATAL); } ap_calc_scoreboard_size(); ap_init_scoreboard(sb_mem); /* Gain access to the accpet mutex */ rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex); if (rc) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, "accept mutex couldn't be accessed in child, exiting"); clean_child_exit(APEXIT_CHILDFATAL); } /* Find our pid in the scoreboard so we know what slot our parent allocated us */ for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++); if (child_slot == HARD_SERVER_LIMIT) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child pid not found in scoreboard, exiting"); clean_child_exit(APEXIT_CHILDFATAL); } ap_my_generation = ap_scoreboard_image->parent[child_slot].generation; memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT); /* Set up an OS/2 queue for passing connections & termination requests * to worker threads */ rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid)); if (rc) { ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, "unable to create work queue, exiting"); clean_child_exit(APEXIT_CHILDFATAL); } /* Create initial pool of worker threads */ for (c = 0; c < ap_min_spare_threads; c++) { // ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c); } /* Start maintenance thread */ server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL); /* Set up poll */ for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) { num_listeners++; } apr_pollset_create(&pollset, num_listeners, pchild, 0); for (lr = ap_listeners; lr != NULL; lr = lr->next) { apr_pollfd_t pfd = { 0 }; pfd.desc_type = APR_POLL_SOCKET; pfd.desc.s = lr->sd; pfd.reqevents = APR_POLLIN; pfd.client_data = lr; apr_pollset_add(pollset, &pfd); } /* Main connection accept loop */ do { apr_pool_t *pconn; worker_args_t *worker_args; int last_poll_idx = 0; apr_pool_create(&pconn, pchild); worker_args = apr_palloc(pconn, sizeof(worker_args_t)); worker_args->pconn = pconn; if (num_listeners == 1) { rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn); } else { const apr_pollfd_t *poll_results; apr_int32_t num_poll_results; rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT); if (shutdown_pending) { DosReleaseMutexSem(ap_mpm_accept_mutex); break; } rv = APR_FROM_OS_ERROR(rc); if (rv == APR_SUCCESS) { rv = apr_pollset_poll(pollset, -1, &num_poll_results, &poll_results); DosReleaseMutexSem(ap_mpm_accept_mutex); } if (rv == APR_SUCCESS) { if (last_poll_idx >= num_listeners) { last_poll_idx = 0; } lr = poll_results[last_poll_idx++].client_data; rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn); last_poll_idx++; } } if (rv != APR_SUCCESS) { if (!APR_STATUS_IS_EINTR(rv)) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_socket_accept"); clean_child_exit(APEXIT_CHILDFATAL); } } else { DosWriteQueue(workq, WORKTYPE_CONN, sizeof(worker_args_t), worker_args, 0); requests_this_child++; } if (ap_max_requests_per_child != 0 && requests_this_child >= ap_max_requests_per_child) break; } while (!shutdown_pending && ap_my_generation == ap_scoreboard_image->global->running_generation); ap_scoreboard_image->parent[child_slot].quiescing = 1; DosPostEventSem(shutdown_event); DosWaitThread(&server_maint_tid, DCWW_WAIT); if (is_graceful) { char someleft; /* tell our worker threads to exit */ for (c=0; c<HARD_THREAD_LIMIT; c++) { if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) { DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0); } } do { someleft = 0; for (c=0; c<HARD_THREAD_LIMIT; c++) { if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) { someleft = 1; DosSleep(1000); break; } } } while (someleft); } else { DosPurgeQueue(workq); for (c=0; c<HARD_THREAD_LIMIT; c++) { if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) { DosKillThread(ap_scoreboard_image->servers[child_slot][c].tid); } } } apr_pool_destroy(pchild); }
int pthread_join(pthread_t pthread, void **thread_return) { int rval = 0; int status = 0; TID tid; pthread_t pthread1; PTHREAD_INIT; /* Block signals: */ _thread_kern_sig_block(&status); /* Point to the first thread in the list: */ pthread1 = _thread_link_list; /* Search for the thread to join to: */ while (pthread1 != NULL && pthread1 != pthread) { /* Point to the next thread: */ pthread1 = pthread1->nxt; } if (pthread1 == NULL) { /* Point to the first thread in the dead thread list: */ pthread1 = _thread_dead; /* Search for the thread to join to: */ while (pthread1 != NULL && pthread1 != pthread) { /* Point to the next thread: */ pthread1 = pthread1->nxt; } } if (pthread1 == NULL) { /* Return an error: */ errno = ESRCH; rval = -1; /* Check if this thread has been detached: */ } else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { /* Return an error: */ errno = ESRCH; rval = -1; } /* Check if the thread is not dead: */ else if (pthread->state != PS_DEAD) { /* Add the running thread to the join queue: */ /* _thread_queue_enq(&(pthread->join_queue), _thread_run); */ _thread_kern_sig_unblock(status); /* Schedule the next thread: */ /* _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); */ PTHREAD_NEW_STATE(_thread_run, PS_JOIN); tid = (pthread)->threadid; DosWaitThread(&tid, DCWW_WAIT); PTHREAD_NEW_STATE(_thread_run, PS_RUNNING); /* Block signals again: */ _thread_kern_sig_block(&status); /* Check if the thread is not detached: */ if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) { /* Check if the return value is required: */ if (thread_return) { /* Return the thread's return value: */ *thread_return = pthread->ret; } } else { /* Return an error: */ errno = ESRCH; rval = -1; } } else { /* Check if the return value is required: */ if (thread_return != NULL) { /* Return the thread's return value: */ *thread_return = pthread->ret; } } /* Unblock signals: */ _thread_kern_sig_unblock(status); /* Return the completion status: */ return (rval); }
void fnSaverThread(void *p) { HWND hwndOldFocus; HWND hwndParent = (HWND) p; HWND hwndOldSysModal; HAB hab; QMSG msg; ULONG ulStyle; // Set our thread to slightly more than regular to be able // to update the screen fine. DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +5, 0); hab = WinInitialize(0); hmqSaverThreadMsgQueue = WinCreateMsgQueue(hab, 0); if (bOnlyPreviewMode) { PFNWP pfnOldWindowProc; // We should run in preview mode, so the hwndParent we have is not the // desktop, but a special window we have to subclass. pfnOldWindowProc = WinSubclassWindow(hwndParent, (PFNWP) fnSaverWindowProc); // Initialize window proc (simulate WM_CREATE) WinSendMsg(hwndParent, WM_SUBCLASS_INIT, (MPARAM) NULL, (MPARAM) NULL); // Also make sure that the window will be redrawn with this new // window proc. WinInvalidateRect(hwndParent, NULL, FALSE); iSaverThreadState = STATE_RUNNING; #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Starting Cairo drawing thread\n"); #endif // Start Cairo drawing thread tidCairoDrawThread = _beginthread(CairoDrawThread, 0, 1024*1024, (void *) hwndParent); #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Entering message loop (Preview)\n"); #endif // Process messages until WM_QUIT! while (WinGetMsg(hab, &msg, 0, 0, 0)) WinDispatchMsg(hab, &msg); #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Leaved message loop (Preview)\n"); #endif #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Stopping Cairo drawing thread\n"); #endif bShutdownDrawing = 1; DosWaitThread(&tidCairoDrawThread, DCWW_WAIT); // Uinitialize window proc (simulate WM_DESTROY) WinSendMsg(hwndParent, WM_SUBCLASS_UNINIT, (MPARAM) NULL, (MPARAM) NULL); // Undo subclassing WinSubclassWindow(hwndParent, pfnOldWindowProc); // Also make sure that the window will be redrawn with the old // window proc. WinInvalidateRect(hwndParent, NULL, FALSE); iSaverThreadState = STATE_STOPPED_OK; } else { // We should run in normal mode, so create a new window, topmost, and everything else... WinRegisterClass(hab, (PSZ) pchSaverWindowClassName, (PFNWP) fnSaverWindowProc, CS_SIZEREDRAW | CS_CLIPCHILDREN | CS_CLIPSIBLINGS, 0); hwndOldFocus = WinQueryFocus(HWND_DESKTOP); // Create the saver output window so that it will be the child of // the given parent window. // Make window 'Always on top' because we'll be in real screensaver mode! ulStyle = WS_VISIBLE | WS_TOPMOST; hwndSaverWindow = WinCreateWindow(HWND_DESKTOP, pchSaverWindowClassName, "Screen saver", ulStyle, 0, 0, (int) WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN), (int) WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN), HWND_DESKTOP, HWND_TOP, 0x9fff, // Some ID.... NULL, NULL); if (!hwndSaverWindow) { #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Could not create window!\n"); #endif // Yikes, could not create window! iSaverThreadState = STATE_STOPPED_ERROR; } else { // Cool, window created! // Make sure nobody will be able to switch away of it! // We do this by making the window system-modal, and giving it the focus! hwndOldSysModal = WinQuerySysModalWindow(HWND_DESKTOP); WinSetSysModalWindow(HWND_DESKTOP, hwndSaverWindow); WinSetFocus(HWND_DESKTOP, hwndSaverWindow); iSaverThreadState = STATE_RUNNING; #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Starting Cairo drawing thread\n"); #endif // Start Cairo drawing thread tidCairoDrawThread = _beginthread(CairoDrawThread, 0, 1024*1024, (void *) hwndSaverWindow); #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Entering message loop (Real)\n"); #endif // Process messages until WM_QUIT! while (WinGetMsg(hab, &msg, 0, 0, 0)) WinDispatchMsg(hab, &msg); #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Leaved message loop (Real)\n"); #endif #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : Stopping Cairo drawing thread\n"); #endif bShutdownDrawing = 1; DosWaitThread(&tidCairoDrawThread, DCWW_WAIT); // Undo system modalling WinSetSysModalWindow(HWND_DESKTOP, hwndOldSysModal); // Window closed, so destroy every resource we created! WinDestroyWindow(hwndSaverWindow); // Restore focus to old window WinSetFocus(HWND_DESKTOP, hwndOldFocus); #ifdef DEBUG_LOGGING AddLog("[fnSaverThread] : STATE_STOPPED_OK\n"); #endif iSaverThreadState = STATE_STOPPED_OK; } } WinDestroyMsgQueue(hmqSaverThreadMsgQueue); WinTerminate(hab); _endthread(); }
/************************************************************************** * * Name : main(argc, argv) * * Description: Initializes the application, gets and dispatches messages * for the client window on thread 1 and terminates the * application when a WM_QUIT message is received. It then * saves the configuration in os2.ini, destroys all OS/2 * PM resources, and terminates. * * The following routine is the Presentation Manager program * main body. The main body of a PM program is concerned with * associating the application with the Presentation Manager * system, creating its message queue, registering and displaying * its main window, servicing its message queue during the time * that the application is active, and disassociating the * application from PM when the user is finished with the * it. The remaining parts of this source module that are * concerned with the Presentation Manager are the application's * window procedures (main window procedure, child window * procedures, and dialog window procedures) that process the * messages associated with the application's various windows. * * Concepts : - obtains anchor block handle and creates message * queue * - creates the main frame window which creates the * main client window * - polls the message queue via Get/Dispatch Msg loop * - upon exiting the loop, exits * * API's : WinInitialize * WinCreateMsgQueue * WinRegisterClass * WinLoadString * WinCreateHelpInstance * WinMessageBox * WinCreateStdWindow * WinQueryWindowULong * WinAssociateHelpInstance * WinAddSwitchEntry * WinGetMsg * WinDispatchMsg * WinRemoveSwitchEntry * WinDestroyHelpInstance * WinDestroyWindow * WinDestroyMsgQueue * WinTerminate * * Parameters : [none] * * Return : Always returns zero. The ANSI standard requires that * main be declared as an INT. * *************************************************************************/ INT main(INT argc, CHAR **argv) { /* Define variables by type */ BOOL bOK; /* Boolean used for return code */ HAB hab; /* PM anchor block handle */ HMQ hmq; /* Message queue handle */ QMSG qmsg; /* Message from message queue */ ULONG ulCtlData; /* Standard window create flags */ HWND hwndFrame; /* Frame window handle */ HWND hwndClient; /* Client area window handle */ HWND hwndHelp; /* Help window handle */ PMAIN_PARM pmp; /* Main parameters structure */ SWCNTRL swctl; /* Struct to add to window list */ HSWITCH hsw; /* Window list handle ret'd */ HELPINIT hmi; /* Struct for help creation */ CHAR szWork[ LEN_WORKSTRING ]; /* General use string work area */ PSZ pszTitle; /* Pointer to program title */ /* normal PM application startup */ hab = WinInitialize( 0 ); hmq = WinCreateMsgQueue( hab, 0 ); /* * Register a class for my client window's behavior. * This class has enough extra window words to hold a pointer. */ bOK = WinRegisterClass( hab, CLASSNAME, WinProc, CS_SIZEREDRAW, sizeof( PMAIN_PARM )); /* * Ensure WinRegisterClass worked ok; if not, present a message box. * ( See pmassert.h. ) */ pmassert( hab, bOK ); /* Load program title and allocate a local copy. Use it in help creation. */ WinLoadString( hab, (HMODULE)NULLHANDLE, PROGRAM_TITLE, LEN_WORKSTRING, szWork ); pszTitle = strdup( szWork ); /* Create help. */ memset( &hmi, 0, sizeof( hmi )); hmi.cb = sizeof( HELPINIT ); hmi.phtHelpTable = (HELPTABLE *)(0xffff0000 | ID_PRTSAMP); hmi.pszHelpWindowTitle = pszTitle; hmi.pszHelpLibraryName = HELP_FILE; hwndHelp = WinCreateHelpInstance( hab, &hmi ); if( ! hwndHelp ) { WinLoadString(hab, (HMODULE)NULLHANDLE, ERRMSG_NO_HELP, LEN_WORKSTRING, szWork); WinMessageBox( HWND_DESKTOP, HWND_DESKTOP, szWork, pszTitle, (USHORT)0, MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL); } /* done with local copy of title text */ free( pszTitle ); /* flags to control creation of window; use on call to WinCreateStdWindow */ ulCtlData = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_MENU | FCF_ACCELTABLE | FCF_HORZSCROLL | FCF_VERTSCROLL; hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE | FS_ICON | FS_SHELLPOSITION, &ulCtlData, CLASSNAME, NULL, /* title text set in prtcreat.c */ 0, /* client style */ (HMODULE)NULLHANDLE, /* resources in exe */ ID_PRTSAMP, &hwndClient ); pmassert( hab, hwndFrame ); pmassert( hab, hwndClient ); /* create.c placed pointer to main params in client's window words; get it */ pmp = (PMAIN_PARM) WinQueryWindowULong( hwndClient, QWL_USER ); /* store help instance handle in main parameter block */ pmp->hwndHelp = hwndHelp; bOK = WinAssociateHelpInstance( hwndHelp, hwndFrame ); pmassert( hab, bOK ); /* Add program to task list. */ memset( &swctl, 0, sizeof( SWCNTRL )); strcpy( swctl.szSwtitle, pmp->pszTitle ); swctl.hwnd = hwndFrame; swctl.uchVisibility = SWL_VISIBLE; swctl.fbJump = SWL_JUMPABLE; hsw = WinAddSwitchEntry( &swctl ); /* first parameter could be a filename, so store for later use */ if (argc > 1) { argv++; strcpy( pmp->szArgFilename, *argv); } /* message loop */ while( WinGetMsg( hab, &qmsg, (HWND)NULLHANDLE, 0, 0 )) { WinDispatchMsg( hab, &qmsg ); } /* clean up */ WinRemoveSwitchEntry( hsw ); WinDestroyHelpInstance( hwndHelp ); WinDestroyWindow( hwndFrame ); WinDestroyMsgQueue( hmq ); WinTerminate( hab ); DosWaitThread( &pmp->tidObjectThread, DCWW_WAIT ); return 0; } /* End of main() */
/* SAVER_PROC This is the entry point into the saver module that is called by the ScreenSaver program. There should be no reason to alter the code. Depending on the requested function, the following tasks are performed: * set the name of the INI file to store and query settings * call the configuration dialog of the saver module * copy the name of the saver module into the supplied buffer * tell if the saver module is enabled * set the "enabled" state of the saver module * start the saver * stop the saver Note that before any processing is done, module configuration data is loaded from the INI-files. */ void EXPENTRY SAVER_PROC(int function, HAB _hab, HWND hwndOwner, char *appname, void *buffer) { hab = _hab; application_name = appname; hwndApplication = hwndOwner; // load all configuration data from INI-file if(function != FUNCTION_SETINIFILENAME) load_configuration_data(); switch(function){ case FUNCTION_SETINIFILENAME: if(buffer != NULL) strcpy(ini_filename, (char *)buffer); else strcpy(ini_filename, ""); return; case FUNCTION_CONFIGURE: // call the configuration dialog WinDlgBox(HWND_DESKTOP, hwndOwner, ConfigureDlgProc, hmodDLL, IDD_CONFIGURE, application_name); return; case FUNCTION_STARTSAVER: // start the saver // get "low priority" state from supplied buffer (BOOL *) low_priority = *((BOOL *)buffer); // query size of screen screenSizeX = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN); screenSizeY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN); // register window class for the saver window WinRegisterClass(hab, (PSZ)modulename, (PFNWP)SaverWindowProc, 0, 0); // create the saver window hwndSaver = WinCreateWindow(HWND_DESKTOP, (PSZ)modulename, (PSZ)NULL, WS_VISIBLE, 0, 0, screenSizeX, screenSizeY, HWND_DESKTOP, HWND_TOP, 0, NULL, NULL); return; case FUNCTION_STOPSAVER: // stop the saver if(low_priority){ stop_priority_thread = TRUE; DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 0, tidPriority); DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 0, tidDraw); DosWaitThread(&tidPriority, DCWW_WAIT); // DosKillThread(tidPriority); ***** kills thread 1 under OS/2 2.11 } // tell drawing-thread to stop stop_draw_thread = TRUE; if(DosWaitThread(&tidDraw, DCWW_NOWAIT) == ERROR_THREAD_NOT_TERMINATED){ // if priority of drawing-thread was set to idle time // priority, set it back to normal value DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, tidDraw); // wait until drawing-thread has ended DosWaitThread(&tidDraw, DCWW_WAIT); } if(hwndSaver != NULLHANDLE){ // move saver window to front WinSetWindowPos(hwndSaver, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER); // destroy saver window WinDestroyWindow(hwndSaver); hwndSaver = NULLHANDLE; } return; case FUNCTION_QUERYNAME: // copy module name to supplied buffer (CHAR *) strcpy(buffer, modulename); return; case FUNCTION_QUERYENABLED: // copy "enabled" state to supplied buffer (BOOL *) *((BOOL *)buffer) = configuration_data.enabled; return; case FUNCTION_SETENABLED: // get new "enabled" state from supplied buffer (BOOL *) configuration_data.enabled = *((BOOL *)buffer); write_profile_data(); return; } // illegal function request WinAlarm(HWND_DESKTOP, WA_ERROR); return; }
void SDL_SYS_WaitThread(SDL_Thread * thread) { TID tid = thread->handle; DosWaitThread(&tid, DCWW_WAIT); }
APIRET MsgBox( PSZ pszTitle, CHAR chIcon, CHAR chButtons, CHAR chHelp, USHORT usNumber, PSZ pszText ) { USHORT usReply; MYMSG msgMyMsg; PMYMSG pMsg; pMsg = &msgMyMsg; /* Set message struct with parameters */ pMsg->tidMyMsg = NULLHANDLE; pMsg->habMyMsg = NULLHANDLE; pMsg->hmqMyMsg = NULLHANDLE; pMsg->hwndMyMsg = NULLHANDLE; if ( pszTitle == NULL ) { strcpy( pMsg->szTitle, MSG_DEFAULT_TITLE ); } else { strncpy( pMsg->szTitle, pszTitle, MSG_TITLE_LEN ); (pMsg->szTitle)[MSG_TITLE_LEN] = EOSTR_CH; } pMsg->chIcon = chIcon; pMsg->chButtons = chButtons; pMsg->chHelp = chHelp; pMsg->usNumber = usNumber; if ( pszText == NULL ) { strcpy( pMsg->szText, EMPTY_STR ); } else { strcpy( pMsg->szText, pszText ); } pMsg->usReply = MSG_RESPONSE_IGNORE; // if msgno not zero then build msg string from msgno // using msgtext for parameters (linefeed delimited), // any excess parameters are to be ignored, any // missing parameters need to be replaced with '<?>' pMsg->usNumber = 0; /* no help just yet */ pMsg->tidMyMsg = _beginthread( MsgBoxThread, NULL, MSG_STACK_SIZE, (PVOID) pMsg ); if ( pMsg->tidMyMsg == -1 ) { DosBeep(750,500); } else { DosWaitThread( &(pMsg->tidMyMsg), DCWW_WAIT ); } usReply = pMsg->usReply; /* now we can extract the reply */ return( usReply ); } /* end MsgBox() */
VOID gropFree(PGROPDATA pGrop) { ULONG ulRC; HMQ hmq; TID tid; ulRC = DosRequestMutexSem( pGrop->hmtxData, 4000 ); if ( ulRC != NO_ERROR ) debug( "DosRequestMutexSem(), rc = %u", ulRC ); hmq = pGrop->hmq; tid = pGrop->tid; // Tune off all callback functions. memset( &pGrop->stCallback, 0, sizeof(GROPCALLBACK) ); DosReleaseMutexSem( pGrop->hmtxData ); if ( ( hmq == NULLHANDLE ) || !WinPostQueueMsg( hmq, WM_QUIT, 0, 0 ) ) { debug( "Hm... have not a thread?..." ); if ( pGrop->fFullscreen ) _setMode( pGrop, pGrop->ulModeIdx, FALSE ); if ( tid != ((TID)(-1)) ) { debug( "WTF?! %p %d", pGrop, tid ); DosKillThread( tid ); } } else if ( DosWaitThread( &tid, DCWW_NOWAIT ) != NO_ERROR ) { debug( "Wait thread semaphore" ); ulRC = DosWaitEventSem( pGrop->hevReady, 4000 ); if ( ulRC != NO_ERROR ) { PVIDEOMODE pMode = &pGrop->stModes.pList[pGrop->stModes.ulDesktopMode]; debug( "DosWaitEventSem(), rc = %u. Kill thread...", ulRC ); DosKillThread( tid ); if ( pGrop->hwndDT != NULLHANDLE ) { debug( "Return to the desktop..." ); pGrop->pVideoSys->fnSetMode( pGrop->pVSData, pMode, FALSE, pGrop->hwndDT, pGrop->hdcDT ); } } else { debug( "Wait thread" ); DosWaitThread( &tid, DCWW_WAIT ); } } else debug( "Thread already terminated." ); // Remove GROP object from the list. ulRC = DosRequestMutexSem( hmtxGropList, SEM_INDEFINITE_WAIT ); if ( ulRC != NO_ERROR ) debug( "DosRequestMutexSem(), rc = %u", ulRC ); lnkseqRemove( &lsGropList, pGrop ); DosReleaseMutexSem( hmtxGropList ); DosCloseEventSem( pGrop->hevReady ); debugFree( pGrop ); debug( "Success." ); }
/* virtual */ void Join() { DosWaitThread(&this->thread, DCWW_WAIT); this->thread = 0; }
int main(int argc, char **argv) { #ifdef _PR_PTHREADS int rv; pthread_t threadID; pthread_attr_t attr; #elif defined(SOLARIS) int rv; thread_t threadID; #elif defined(WIN32) DWORD rv; unsigned threadID; HANDLE hThread; #elif defined(IRIX) int rv; int threadID; #elif defined(OS2) int rv; TID threadID; #elif defined(XP_BEOS) thread_id threadID; int32 threadRV; status_t waitRV; #endif /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name [-d] [-c n] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; case 'c': /* loop count */ count = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); #if defined(WIN16) printf("attach: This test is not valid for Win16\n"); goto exit_now; #endif if(0 == count) count = DEFAULT_COUNT; /* * To force the implicit initialization of nspr20 */ PR_SetError(0, 0); PR_STDIO_INIT(); /* * Platform-specific code to create a native thread. The native * thread will repeatedly call PR_AttachThread and PR_DetachThread. * The primordial thread waits for this new thread to finish. */ #ifdef _PR_PTHREADS rv = _PT_PTHREAD_ATTR_INIT(&attr); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #ifndef _PR_DCETHREADS rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #endif /* !_PR_DCETHREADS */ rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL); if (rv != 0) { fprintf(stderr, "thread creation failed: error code %d\n", rv); failed_already=1; goto exit_now; } else { if (debug_mode) printf ("thread creation succeeded \n"); } rv = _PT_PTHREAD_ATTR_DESTROY(&attr); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } rv = pthread_join(threadID, NULL); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #elif defined(SOLARIS) rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID); if (rv != 0) { if(!debug_mode) { failed_already=1; goto exit_now; } else fprintf(stderr, "thread creation failed: error code %d\n", rv); } rv = thr_join(threadID, NULL, NULL); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #elif defined(WIN32) hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID); if (hThread == 0) { fprintf(stderr, "thread creation failed: error code %d\n", GetLastError()); failed_already=1; goto exit_now; } rv = WaitForSingleObject(hThread, INFINITE); if (debug_mode)PR_ASSERT(rv != WAIT_FAILED); else if (rv == WAIT_FAILED) { failed_already=1; goto exit_now; } #elif defined(IRIX) threadID = sproc(threadStartFunc, PR_SALL, NULL); if (threadID == -1) { fprintf(stderr, "thread creation failed: error code %d\n", errno); failed_already=1; goto exit_now; } else { if (debug_mode) printf ("thread creation succeeded \n"); sleep(3); goto exit_now; } rv = waitpid(threadID, NULL, 0); if (debug_mode) PR_ASSERT(rv != -1); else if (rv != -1) { failed_already=1; goto exit_now; } #elif defined(OS2) threadID = (TID) _beginthread((void *)threadStartFunc, NULL, 32768, NULL); if (threadID == -1) { fprintf(stderr, "thread creation failed: error code %d\n", errno); failed_already=1; goto exit_now; } rv = DosWaitThread(&threadID, DCWW_WAIT); if (debug_mode) { PR_ASSERT(rv == NO_ERROR); } else if (rv != NO_ERROR) { failed_already=1; goto exit_now; } #elif defined(XP_BEOS) threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL); if (threadID <= B_ERROR) { fprintf(stderr, "thread creation failed: error code %08lx\n", threadID); failed_already = 1; goto exit_now; } if (resume_thread(threadID) != B_OK) { fprintf(stderr, "failed starting thread: error code %08lx\n", threadID); failed_already = 1; goto exit_now; } waitRV = wait_for_thread(threadID, &threadRV); if (debug_mode) PR_ASSERT(waitRV == B_OK); else if (waitRV != B_OK) { failed_already = 1; goto exit_now; } #else if (!debug_mode) failed_already=1; else printf("The attach test does not apply to this platform because\n" "either this platform does not have native threads or the\n" "test needs to be written for this platform.\n"); goto exit_now; #endif exit_now: if(failed_already) return 1; else return 0; }