コード例 #1
0
ファイル: Fiber.cpp プロジェクト: yorung/MySnippets
int main(int argc, WCHAR* argv[])
{
	fiberA = CreateFiber(0, (LPFIBER_START_ROUTINE)FiberA, (LPVOID)0);
	fiberB = CreateFiber(0, (LPFIBER_START_ROUTINE)FiberB, (LPVOID)0);
	mainFiber = ConvertThreadToFiber(NULL);
	for (int i = 0; i < 20; i++) {
		SwitchToFiber(fiberA);
		SwitchToFiber(fiberB);
		Sleep(100);
	}
	return 0;
}
コード例 #2
0
ファイル: fibers.cpp プロジェクト: rserban/chrono_models
void RunTimeStep(T* mSys, const int frame) {

	if (frame % 100 == 0 && frame * timestep < 20) {
		for (int i = 0; i < 40; i++) {
			CreateFiber(mSys, Vector(2 - 1.6 * 0, 3, i / 8.0));
			CreateFiber(mSys, Vector(2 - 1.6 * 1, 3, i / 8.0));
			CreateFiber(mSys, Vector(2 - 1.6 * 2, 3, i / 8.0));
			CreateFiber(mSys, Vector(2 - 1.6 * 3, 3, i / 8.0));
			fibers += 4;
		}
		cout << "Fibers: " << fibers << endl;
	}
}
コード例 #3
0
ファイル: coroutine.cpp プロジェクト: ennis/rift
void Coroutine::init()
{
	if (!IsThreadAFiber())
		pImpl->pReturnFiber = ConvertThreadToFiber(NULL);
	else 
		pImpl->pReturnFiber = GetCurrentFiber();
	pImpl->pFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)Coroutine::Anonymous::coroutineEntry, pImpl.get());
}
コード例 #4
0
ファイル: context.cpp プロジェクト: Mirocow/balancer
TContMachineContext::TContMachineContext(const TContClosure& c)
    : Fiber_(CreateFiber(c.Stack.Len, (LPFIBER_START_ROUTINE)ContextTrampoLine, (LPVOID)c.TrampoLine))
    , MainFiber_(false)
{
    if (!Fiber_) {
        ythrow yexception() << "fiber error";
    }
}
コード例 #5
0
ファイル: taurus_imp.cpp プロジェクト: holyreaper/syyserver
inline int setup_coroutine(cothread_ctx* tctx, coroutine* c, size_t ssize)
{
	c->ctx = CreateFiber(ssize, &FiberFunc, tctx);
	if (c->ctx == NULL)
	{
	}
	c->stk_size = ssize;
	return (c->ctx==NULL) ? -1 : 0;
}
コード例 #6
0
ファイル: coroutine-win32.c プロジェクト: 0bliv10n/s2e
Coroutine *qemu_coroutine_new(void)
{
    const size_t stack_size = 1 << 20;
    CoroutineWin32 *co;

    co = g_malloc0(sizeof(*co));
    co->fiber = CreateFiber(stack_size, coroutine_trampoline, &co->base);
    return &co->base;
}
コード例 #7
0
ファイル: Coroutine.cpp プロジェクト: LazyPlanet/GameLib
	INT32 CoCreate(void ** pCoID, coroutine_func pFunc, void * pArg)
	{
		*pCoID = CreateFiber(0, pFunc, pArg);
		if (*pCoID == NULL)
		{
			gErrorStream("create fiber failed.\n");
		}

		return 0;
	}
コード例 #8
0
ファイル: FiberWin32.cpp プロジェクト: ixc-software/lucksi
        FiberImpl(const BodyFn &fn, int stackSize) : m_bodyFn(fn), m_fiberToReturn(0)
        {
            ESS_ASSERT(fn);
            if (stackSize <= 0) stackSize = CDefaultStackSize;

            MainThreadInit();

            // create fiber
            m_handle = CreateFiber(stackSize, &FiberImpl::FiberFunc, this);
            ESS_ASSERT(m_handle != 0);
        }
コード例 #9
0
struct ff_arch_fiber *ff_arch_fiber_create(ff_arch_fiber_func arch_fiber_func, void *ctx, int stack_size)
{
	struct ff_arch_fiber *fiber;

	ff_assert(stack_size > 0);

	fiber = (struct ff_arch_fiber *) ff_malloc(sizeof(*fiber));
	fiber->handle = CreateFiber(stack_size, (LPFIBER_START_ROUTINE) arch_fiber_func, ctx);
	ff_winapi_fatal_error_check(fiber->handle != NULL, L"cannot create new fiber");
	return fiber;
}
コード例 #10
0
ファイル: coro.c プロジェクト: AlwaysGeeky/nanogui
void
coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ssize)
{
  ctx->fiber = 0;
  ctx->coro  = coro;
  ctx->arg   = arg;

  if (!coro)
    return;

  ctx->fiber = CreateFiber (ssize, coro_init, ctx);
}
コード例 #11
0
ファイル: uthread_win32.cpp プロジェクト: ricky26/netlib
	uthread_impl *uthread_create(uthread::uthread_start_t _start, void *_param)
	{
		uthread_impl *cur = ::netlib::current();
		handle<uthread_impl> thr = new uthread_impl(_start, _param);

		// 1 <-- creates the smallest possible stack, it can grow, worry not.
		void *fib = CreateFiber(1, (LPFIBER_START_ROUTINE)&uthread_fiber_start, thr.get());
		if(!fib)
			return NULL;

		thr->fiber = fib;
		return thr.get();
	}
コード例 #12
0
ファイル: thread-win32.c プロジェクト: IlVerz/rockbox
static inline void load_context(const void* addr)
{
    struct regs *context = (struct regs*)addr;
    if (UNLIKELY(context->start))
    {   /* need setup before switching to it */
        context->uc = CreateFiber(context->stack_size,
                        (LPFIBER_START_ROUTINE)start_thread, context->start);
        /* can't assign stack pointer, only stack size */
        context->stack_size = 0;
        context->start = NULL;
    }
    SwitchToFiber(context->uc);
}
コード例 #13
0
ファイル: fiber.cpp プロジェクト: rod-lin/ink
int InkCoro_Scheduler::create(InkCoro_Function fp, void *arg)
{
	InkCoro_Routine *co = new InkCoro_Routine();

	co->fib = CreateFiber(0, (LPFIBER_START_ROUTINE)wrapper,
						  co->tmp_arg = new InkCoro_Scheduler_wrapper_arg(this, co));
	co->func = fp;
	co->arg = arg;

	pool.push_back(co);

	return 0;
}
コード例 #14
0
ファイル: realmain.c プロジェクト: NRauh/wordgrinder
int main(int argc, const char* argv[])
{
	InitCommonControls();

	if (AttachConsole(ATTACH_PARENT_PROCESS))
	{
		freopen("CONOUT$", "wb", stdout);
		freopen("CONOUT$", "wb", stderr);
	}

	uifiber = ConvertThreadToFiber(NULL);
	assert(uifiber);

	appfiber = CreateFiber(0, application_cb, NULL);
	assert(appfiber);

	realargc = argc;
	realargv = argv;

	/* Run the application fiber. This will deschedule when it wants an
	 * event.
	 */

	SwitchToFiber(appfiber);

	/* And now the event loop. */

	int oldtimeout = -1;
	for (;;)
	{
		MSG msg;

		dpy_flushkeys();

		if (timeout != oldtimeout)
		{
			if (timeout == -1)
				KillTimer(window, TIMEOUT_TIMER_ID);
			else
				SetTimer(window, TIMEOUT_TIMER_ID, timeout*1000, NULL);
			oldtimeout = timeout;
		}

		GetMessageW(&msg, NULL, 0, 0);

		if (DispatchMessageW(&msg) == 0)
			TranslateMessage(&msg);
	}

	return 0;
}
コード例 #15
0
        bool Fiber::Init(int threadIndex, unsigned stackSize, FiberPool* ownerPool)
        {
            if (m_threadIndex >= 0)
                return false;
            m_threadIndex = threadIndex;

#if defined(WINDOWS)
            m_fiber = CreateFiber(stackSize, &FiberMain, this);
#endif
            m_ownerPool = ownerPool;
            if (m_fiber == false)
                return false;
            return true;
        }
コード例 #16
0
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // Reset data
    i = 0;
    memset( buffer, 0, sizeof(buffer) );

    // Convert this thread
    g_pFibers[FIBER_PRIMARY] = ConvertThreadToFiber( NULL );

    // Create the fibers
    g_pFibers[FIBER1] = CreateFiber( 0, Fiber1, NULL );
    g_pFibers[FIBER2] = CreateFiber( 0, Fiber2, NULL );

    // Execute the fibers
    SwitchToFiber( g_pFibers[FIBER1] );

    // Terminate the input
    buffer[i++] = '\0';

    DeleteFiber( g_pFibers[FIBER1] );
    DeleteFiber( g_pFibers[FIBER2] );

    OutputDebugString( buffer );
}
コード例 #17
0
int coroutine_init(struct coroutine *co)
{
	if (leader.fiber == NULL) {
		leader.fiber = ConvertThreadToFiber(&leader);
		if (leader.fiber == NULL)
			return -1;
	}

	co->fiber = CreateFiber(0, &coroutine_trampoline, co);
	co->ret = 0;
	if (co->fiber == NULL)
		return -1;

	return 0;
}
コード例 #18
0
/*
 * implementation for context_call
 */
void *  context_call(sc_context *  pContext,
                     pcontext_call_routine f,
                     void *  prm) {

  assert(pContext != NULL);
  assert(f        != NULL);

  if (pContext->pFiber != NULL) context_complete(pContext);
  pContext->pRoutine      = f;
  pContext->pParameter    = (void **)malloc(sizeof(void *));
  *(pContext->pParameter) = prm;
  pContext->pParent       = current_context;
  pContext->state         = FS_PREPARED;
  pContext->pFiber        = CreateFiber(pContext->stack_size, fp, pContext);
  return context_recall(pContext);
}
コード例 #19
0
ファイル: Coro.c プロジェクト: doublec/io
void Coro_setup(Coro *self, void *arg)
{
	// If this coro was recycled and already has a fiber, delete it.
	// Don't delete the main fiber. We don't want to commit suicide.

	if (self->fiber && !self->isMain)
	{
		DeleteFiber(self->fiber);
	}

	self->fiber = CreateFiber(Coro_stackSize(self),
							  (LPFIBER_START_ROUTINE)Coro_StartWithArg,
							 (LPVOID)arg);
	if (!self->fiber) {
		DWORD err = GetLastError();
		exit(err);
	}
}
コード例 #20
0
ファイル: lwp_nt.c プロジェクト: maxendpoint/openafs_cvs
/* LWP_CreateProcess - create a new fiber and start executing it.
 *
 * Arguments:
 *	funP - start function
 *	stacksize - size of 
 *	priority - LWP priority
 *	argP - initial parameter for start function
 *	name - name of LWP
 *
 * Return:
 *	pid - handle of created LWP
 *	value:
 *	0 - success
 *	LWP_EINIT - error in intialization.
 *
 */
int LWP_CreateProcess(int (*funP)(), int stacksize, int priority, void *argP,
		      char *name, PROCESS *pid)
{
    PROCESS pcb;
    
    purge_dead_pcbs();

    pcb = (PROCESS)malloc(sizeof(*pcb));
    if (pcb == NULL)
	return LWP_ENOMEM;
    (void) memset((void*)pcb, 0, sizeof(*pcb));

    /*
     * on some systems (e.g. hpux), a minimum usable stack size has
     * been discovered
     */
    if (stacksize < lwp_MinStackSize) {
      stacksize = lwp_MinStackSize;
    }
    /* more stack size computations; keep track of for IOMGR */
    if (lwp_MaxStackSeen < stacksize)
	lwp_MaxStackSeen = stacksize;

    pcb->fiber = CreateFiber(stacksize, Enter_LWP, pcb);
    if (pcb->fiber == NULL) {
	free((void*)pcb);
	return LWP_EINIT;
    }
    Debug(0, ("Create: pcb=0x%p, funP=0x%p, argP=0x%p\n", pcb, funP, argP))
    /* Fiber is now created, so fill in PCB */
    Initialize_PCB(pcb, priority, stacksize, funP, argP, name);
    Debug(10, ("Create: Insert 0x%p into runnable at priority %d\n", pcb, priority))
    insert(pcb, &runnable[priority]);

    LWPANCHOR.processcnt++;

    /* And hand off execution. */
    SwitchToFiber(pcb->fiber);

    *pid = pcb;

    return LWP_SUCCESS;
}
コード例 #21
0
ファイル: pthreads_win32.c プロジェクト: Ferada/sbcl
/* Create thread or fiber, depending on current thread's "fiber
   factory mode". In the latter case, switch into newly-created fiber
   immediately.
*/
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg)
{
  pthread_t pth = (pthread_t)calloc(sizeof(pthread_thread),1);
  pthread_t self = pthread_self();
  int i;
  HANDLE createdThread = NULL;

  if (self && self->fiber_factory) {
    pth->fiber = CreateFiber (attr ? attr->stack_size : 0, Fiber_Function, pth);
    if (!pth->fiber) return 1;
    pth->created_as_fiber = 1;
    /* Has no fiber-group until someone enters it (we will) */
  } else {
    createdThread = CreateThread(NULL, attr ? attr->stack_size : 0,
                                 Thread_Function, pth, CREATE_SUSPENDED, NULL);
    if (!createdThread) return 1;
    /* FCAT is its own fiber-group [initially] */
    pth->fiber_group = pth;
    pth->handle = createdThread;
  }
  pth->start_routine = start_routine;
  pth->arg = arg;
  if (self) {
    pth->blocked_signal_set = self->blocked_signal_set;
  } else {
    sigemptyset(&pth->blocked_signal_set);
  }
  pth->state = pthread_state_running;
  pthread_mutex_init(&pth->lock, NULL);
  pthread_mutex_init(&pth->fiber_lock, NULL);
  pthread_cond_init(&pth->cond, NULL);
  pth->detached = 0;
  if (thread) *thread = pth;
  if (pth->fiber) {
    pthread_np_switch_to_fiber(pth);
  } else {
    /* Resume will unlock, so we lock here */
    pthread_mutex_lock(&pth->fiber_lock);
    pthread_np_resume(pth);
  }
  return 0;
}
コード例 #22
0
ファイル: Main.cpp プロジェクト: Alo81/scripthookvdotnet
void ScriptMainSetup()
{
	sGameReloaded = true;
	sMainFib = GetCurrentFiber();

	if (sScriptFib == nullptr)
	{
		// Create our own fiber for the common language runtime once
		sScriptFib = CreateFiber(0, reinterpret_cast<LPFIBER_START_ROUTINE>(&ScriptMainLoop), nullptr);
	}

	while (true)
	{
		// Yield execution
		scriptWait(0);

		// Switch to our own fiber and wait for it to switch back
		SwitchToFiber(sScriptFib);
	}
}
コード例 #23
0
ファイル: ntthread.c プロジェクト: Akin-Net/mozilla-central
void
_PR_MD_INIT_CONTEXT(PRThread *thread, char *top, void (*start) (void), PRBool *status)
{
    thread->md.fiber_fn = (void (*)(void *))start;
    thread->md.fiber_id = CreateFiber(thread->md.fiber_stacksize, 
        (LPFIBER_START_ROUTINE)_pr_fiber_mainline, NULL);
    if (thread->md.fiber_id != 0)
        *status = PR_TRUE;
    else {
        DWORD oserror = GetLastError();
        PRErrorCode prerror;
        if (oserror == ERROR_NOT_ENOUGH_MEMORY) {
            prerror = PR_OUT_OF_MEMORY_ERROR;
        } else {
            prerror = PR_UNKNOWN_ERROR;
        }
        PR_SetError(prerror, oserror);
        *status = PR_FALSE;
    }
}
コード例 #24
0
ファイル: mtarch.c プロジェクト: Asterios/contiki-econotag
/*--------------------------------------------------------------------------*/
void
mtarch_start(struct mtarch_thread *thread,
	     void (* function)(void *data),
	     void *data)
{
#if defined(_WIN32) || defined(__CYGWIN__)

  thread->mt_thread = CreateFiber(0, (LPFIBER_START_ROUTINE)function, data);

#else /* _WIN32 || __CYGWIN__ */

  thread->mt_thread = malloc(sizeof(struct mtarch_t));

  getcontext(&((struct mtarch_t *)thread->mt_thread)->context);

  ((struct mtarch_t *)thread->mt_thread)->context.uc_link = NULL;
  ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_sp = 
			((struct mtarch_t *)thread->mt_thread)->stack;
  ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_size = 
			sizeof(((struct mtarch_t *)thread->mt_thread)->stack);

  /* Some notes:
     - If a CPU needs stronger alignment for the stack than malloc()
       guarantees (like i.e. IA64) then makecontext() is supposed to
       add that alignment internally.
     - According to POSIX the arguments to function() are of type int
       and there are in fact 64-bit implementations which support only
       32 bits per argument meaning that a pointer argument has to be
       splitted into two arguments.
     - Most implementations interpret context.uc_stack.ss_sp on entry
       as the lowest stack address even if the CPU stack actually grows
       downwards. Although this means that ss_sp does NOT represent the
       CPU stack pointer this behaviour makes perfectly sense as it is
       the only way to stay independent from the CPU architecture. But
       Solaris prior to release 10 interprets ss_sp as highest stack
       address thus requiring special handling. */
  makecontext(&((struct mtarch_t *)thread->mt_thread)->context,
	      (void (*)(void))function, 1, data);

#endif /* _WIN32 || __CYGWIN__ */
}
コード例 #25
0
ファイル: coroutine.c プロジェクト: Strongc/EffiLib
void coroutine_resume(struct schedule * S, int id) 
{
    //         assert(S->running == -1);
    //         assert(id >=0 && id < S->cap);
    struct coroutine *C = S->co[id];
    int status;
    if (C == NULL)
        return;
    status = C->status;
    switch(status) {
    case COROUTINE_READY:
        C->ctx = CreateFiber(0, fiberProc, (void*)S);
    case COROUTINE_SUSPEND:
        S->running = id;
        C->status = COROUTINE_RUNNING;
        SwitchToFiber(C->ctx);
        break;
    default:
        assert(0);
    }
}
コード例 #26
0
ファイル: acid64.cpp プロジェクト: mwgoldsmith/sidplay2-libs
__declspec(dllexport) handle_t __stdcall createC64 ()
{
    handle_t handle = 0;

    try
    {
        std::auto_ptr<Acid64> inst(new Acid64);
        inst->engine = ISidplay2::create ();
        if (!inst->engine)
            throw 0;
        inst->cycleCorrection = 0;
        inst->cpuClock = 0.0;
        inst->builder.create (inst->engine->info().maxsids);

        // Create the fiber
        inst->engineFiber = CreateFiber (0, &start, inst.get());
        if (!inst->engineFiber)
            throw 0;

        try
        {
            SafeThreadToFibre convert(inst->mainFiber);
            SwitchToFiber (inst->engineFiber);
        }
        catch (...)
        {
            DeleteFiber (inst->engineFiber);
            throw;
        }

        handle = (handle_t)inst.get ();
        inst.release ();
    }
    catch (...)
    {
        ;
    }

    return handle;
}
コード例 #27
0
ファイル: Fiber.cpp プロジェクト: Rn86/Boron
		Impl(FiberUID uid, const FiberCallback & callback, size_t szStack)
			: Impl(uid, CreateFiber(szStack, (LPFIBER_START_ROUTINE)FiberDispatcher::Dispatch, new FiberDispatcher(callback)))
		{
		}
コード例 #28
0
void jsInit()
{
#ifdef DEBUG_OUTPUT
	g_pDebugLog = fopen("JS_DEBUG.log", "w");
#endif 

	//find number of cores
	SYSTEM_INFO sysInfo = { 0 };
	GetSystemInfo(&sysInfo);
	g_numProcessors = sysInfo.dwNumberOfProcessors;


	//spawn fibers
	for (int i = 0; i < NUM_FIBERS; ++i)
	{
		g_fibers[i].fiber = CreateFiber(FIBER_STACK_SIZE, fiberRoutine, g_fibers + i);
		g_fibers[i].pNextInWaitList = NULL;
		g_fibers[i].status = UNUSED;
		g_pFiberPool[NUM_FIBERS - 1 - i] = g_fibers + i;
	}


	//init waiting fibers
	memset(g_waitingFibers, 0, sizeof(g_waitingFibers));
	g_waitingFiberHead = 0;
	g_waitListTail.pFiber = NULL;
	g_waitListTail.pNextWaitingFiber = NULL;
	g_waitListTail.time = 0;

	//get performance frequency
	QueryPerformanceFrequency((LARGE_INTEGER*)&g_performanceFrequency);

	//init jobs
	for (int i = 2; i < MAX_JOBS; ++i)
	{
		g_jobs[i - 1].pNextJob = g_jobs + i;
	}
	g_pFreeJob = g_jobs + 1;
	g_pJobQueueHead = g_jobs;
	g_dummyJob.threadId = 0x0;
	g_dummyJob.pNextJob = g_pJobQueueHead;
	g_dummyJob.pName = "__dummy";

	//spawn threads
	g_threadData = TlsAlloc();

	for (int i = 0; i < g_numProcessors; ++i)
	{
		//create thread
		if (i == 0)
		{
			g_threads[0].handle = GetCurrentThread();
		}
		else
		{
			g_threads[i].handle = CreateThread(NULL, 0, threadStart, g_threads + i, 0, NULL);
		}

		g_threads[i].id = 0x1 << i;
		g_threads[i].ppJobQueueTail = &(g_dummyJob.pNextJob);



		//lock thread to specific cpu
		SetThreadAffinityMask(g_threads[i].handle, 1 << i);
	}
	TlsSetValue(g_threadData, g_threads + 0);

	initCounterAllocator();

#ifdef DEBUG_OUTPUT
	fprintf(g_pDebugLog, "%lld \t jobsystem started\n", time(NULL));
#endif

}
コード例 #29
0
ファイル: WinFiber.cpp プロジェクト: Apodus/game_one
Fiber::Fiber() {
	m_fiber = CreateFiber(0, Fiber::fiberStartingFunction, this);
	m_isThread = false;
}
コード例 #30
0
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {

   // Counter fiber execution context
   PVOID pFiberCounter = NULL;   

   // Convert this thread to a fiber.

   /* Converts the current thread into a fiber. 
    * You must convert a thread into a fiber 
	* before you can schedule other fibers. */
   g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL);

   /* Allocates a fiber local storage (FLS) index. 
    * Any fiber in the process can subsequently use this index 
	* to store and retrieve values that are local to the fiber. */
   g_dwSlot = FlsAlloc(LogMessage);
   FlsSetValue(g_dwSlot, TEXT("UI fiber"));


   // Create the application's UI window.
   g_FiberInfo.hwnd = CreateDialog(hinstExe, MAKEINTRESOURCE(IDD_COUNTER), 
      NULL, Dlg_Proc);

   // Update the window showing which fiber is executing.
   SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("User interface"));

   // Initially, there is no background processing to be done.
   g_FiberInfo.bps = BPS_DONE;

   // While the UI window still exists...
   BOOL fQuit = FALSE;
   while (!fQuit) {

      // UI messages are higher priority than background processing.
      MSG msg;
	  /* Dispatches incoming sent messages, checks 
	   * the thread message queue for a posted message, 
	   * and retrieves the message (if any exist). 
	   * PM_REMOVE 0x0001 
	   * Messages are removed from the queue after processing by PeekMessage.
	   */
      if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {

         // If a message exists in the queue, process it.
	     /* Determines whether a message is intended 
		  * for the specified dialog box and, 
		  * if it is, processes the message. 
		  * hDlg [in] Type: HWND A handle to the dialog box.
          * lpMsg [in] Type: LPMSG A pointer to an MSG structure 
		  * that contains the message to be checked.
		  */
         if (!IsDialogMessage(g_FiberInfo.hwnd, &msg)) 
		 {
			 /* Translates virtual-key messages into character messages. 
			  * The character messages are posted to the calling thread's message queue, 
			  * to be read the next time the thread calls the GetMessage or PeekMessage function */
             TranslateMessage(&msg);
			 /* Dispatches a message to a window procedure. 
			  * It is typically used to dispatch a message retrieved by the GetMessage function. */
             DispatchMessage(&msg);
         }

         fQuit = (msg.message == WM_QUIT);
         
         if (fQuit)
         {
            // Release FLS slot
            FlsFree(g_dwSlot);

            // The background processing must be stopped. 
            if (pFiberCounter != NULL) { 
               // A recalculation fiber exists; delete it
               DeleteFiber(pFiberCounter); 
               pFiberCounter = NULL; 
            }
         
            // Quit the fiber mode and return to simple thread mode
            ConvertFiberToThread();
            g_FiberInfo.pFiberUI = NULL;
         }
         
      } else {

         // No UI msgs exist; check the state of the background processing.
         switch (g_FiberInfo.bps) {
            case BPS_DONE:
               // No background processing to do; wait for a UI event.
               /* Yields control to other threads when a thread has no other messages 
			    * in its message queue. 
				* The WaitMessage function suspends the thread 
				* and does not return until a new message 
				* is placed in the thread's message queue. */
               WaitMessage();
               break;

            case BPS_STARTOVER:
               // User changed the count; 
               // cancel the current background processing.
               if (pFiberCounter != NULL) { 
                  // A recalculation fiber exists; delete it so that
                  // background processing starts over from the beginning.
                  DeleteFiber(pFiberCounter); 
                  pFiberCounter = NULL; 
               }

               // Convert this thread to a fiber if needed.
               if (g_FiberInfo.pFiberUI == NULL)
                  g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL);

               LogMessage(TEXT("convert UI thread to fiber..."));

               // Create a new recalc fiber that starts from the beginning.
               pFiberCounter = CreateFiber(0, FiberFunc, &g_FiberInfo);

               // The background processing started; it should continue.
               g_FiberInfo.bps = BPS_CONTINUE;

               // Fall through to BPS_CONTINUE case...

            case BPS_CONTINUE:
               // Allow the background processing to execute...
               SwitchToFiber(pFiberCounter);

               // The background processing has been paused 
               // (because a UI message showed up) or has been 
               // stopped (because the counting has completed).

               // Update the window showing which fiber is executing.
               SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, 
                  TEXT("User interface"));

               if (g_FiberInfo.bps == BPS_DONE) { 
                  // The background processing ran to completion. Delete the
                  // fiber so that processing will restart next time.
                  DeleteFiber(pFiberCounter); 
                  pFiberCounter = NULL; 
               
                  // Quit the fiber mode and return to simple thread mode
                  ConvertFiberToThread();
                  g_FiberInfo.pFiberUI = NULL;
               }
               break;
         }  // switch on background processing state

      }  // No UI messages exist
   }  // while the window still exists

   DestroyWindow(g_FiberInfo.hwnd); 

   return(0);  // End the application.
}