00001 
00034 #include "stdafx.h"
00035 
00036 namespace AxPipe {
00046     CCoContext::CCoContext(CError *pErr, void (*pfStart)(void *), void *pvParam) {
00047         m_pFiber = NULL;
00048         Init(pErr, pfStart, pvParam);
00049     }
00050 
00055     void
00056     CCoContext::Init(CError *pErr, void (*pfStart)(void *), void *pvParam) {
00057         m_pErr = pErr;
00058         m_pfStart = pfStart;
00059         m_pvParam = pvParam;
00060     }
00061     
00067     CCoContext::~CCoContext() {
00068         Stop();
00069     }
00070 
00072     VOID CALLBACK
00073     CCoContext::Start(PVOID lpParam) {
00074         ((CCoContext *)lpParam)->m_pfStart(((CCoContext *)lpParam)->m_pvParam);
00075         
00076     }
00077     
00088     bool
00089     CCoContext::Go() {
00090         
00091         
00092         if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
00093             m_pErr->SetError(ERROR_CODE_INTERNAL, ERROR_MSG_INTERNAL, _T("CoContext::Go() [No TLS available]"));
00094             return false;
00095         }
00096         
00097         if (!m_pFiber) {
00098             m_dwThreadId = GetCurrentThreadId();
00099             
00100             if (!m_pfStart) {
00101                 
00102                 
00103                 if (TlsGetValue(dwTlsIndex) == NULL) {
00104                     
00105                     m_pFiber = ConvertThreadToFiber(0);
00106                     
00107                     
00108                     TlsSetValue(dwTlsIndex, (LPVOID)true);
00109                 } else {
00110                     
00111                     m_pFiber = GetCurrentFiber();
00112                 }
00113                 
00114 
00115                 
00116                 
00117                 
00118                 return true;
00119             }
00120             
00121             
00122             
00123             m_pFiber = CreateFiber(0, Start, this);
00124             
00125         }
00126         
00127         ASSCHK(TlsGetValue(dwTlsIndex) != NULL, _T("CoContext::Go() [Attempt to switch to fiber from non-fiber]"));
00128 
00129         
00130         SwitchToFiber(m_pFiber);
00131         
00132         return true;
00133     }
00134 
00143     void
00144     CCoContext::Stop() {
00145         
00146         if (m_pFiber && m_pfStart) {
00147             
00148             if (m_pFiber != GetCurrentFiber()) {
00149                 
00150                 DeleteFiber(m_pFiber);
00151                 m_pFiber = NULL;
00152             } else {
00153                 
00154                 ASSCHK(false, _T("Attempting to stop self"));
00155             }
00156         }
00157     }
00158 };