Example #1
0
unsigned int Timer::Run()
{
	//high_resolution_clock::time_point point = high_resolution_clock::now();
	//duration<long double> timeSpan = duration_cast<duration<long double>>(point - m_start);
	
	//double newTime = timeSpan.count() * 1000.0;
	double newTime = (GetCurrentTimeMS() - m_startTime);
	m_deltaTime = newTime - m_totalTime;
	m_totalTime = newTime;

	if (m_ticks < TICKS_TO_UNLOCK_FIXED)
	{
		m_fixedDelta += m_deltaTime;
	}
	else if (m_ticks == TICKS_TO_UNLOCK_FIXED)
	{
		m_deltaTime /= (double)TICKS_TO_UNLOCK_FIXED;
	}

	m_fps = 1000.0 / (m_deltaTime);
	++m_ticks;

	//printf("%f, %f, %f\n", m_totalTime, m_deltaTime, m_fps);
	//LOGI("Timer: %f, %f, %f, %d", m_totalTime, m_deltaTime, m_fps, m_ticks);

	return CS_ERR_NONE;
}
Example #2
0
//******************************************************************************
//
//	Radio Hold To Talk Simulation
//
//******************************************************************************
WORD RadioSimStartRx(MODEM_ID	modemID)
{
	TestRadioSystem.ModemState[modemID] = MODEM_TRANSITION_TO_RECEIVE_STATE;
	TestRadioSystem.ModemTransitionRandomDelayMS[modemID] = 
		RandWord(RADIO_TRANS_TO_RECEIVE_MIN_WAIT_MS, RADIO_TRANS_TO_RECEIVE_MAX_WAIT_MS);
	TestRadioSystem.ModemTransitionStartTimeMS[modemID] = GetCurrentTimeMS();
	return TRUE;
}
String AutotestingSystem::GetCurrentTimeString()
{
    uint64 timeAbsMs = GetCurrentTimeMS();

    uint16 hours = (timeAbsMs/3600000)%12;
    uint16 minutes = (timeAbsMs/60000)%60;
    uint16 seconds = (timeAbsMs/1000)%60;
	//Logger::Debug("TIME: %02d:%02d:%02d", hours, minutes, seconds);
    return Format("%02d:%02d:%02d", hours, minutes, seconds);
}
void AutotestingSystem::MakeScreenShot()
{
	Logger::Debug("AutotestingSystem::MakeScreenShot");
	uint64 timeAbsMs = GetCurrentTimeMS();
    uint16 hours = (timeAbsMs/3600000)%24;
    uint16 minutes = (timeAbsMs/60000)%60;
    uint16 seconds = (timeAbsMs/1000)%60;
	screenShotName = Format("%s_%s_%s_%02d_%02d_%02d", AUTOTESTING_PLATFORM_NAME, deviceName.c_str(), groupName.c_str(), hours, minutes, seconds);

	RenderManager::Instance()->RequestGLScreenShot(this);
}
Example #5
0
unsigned int Timer::Initialize()
{
#ifdef PLATFORM_WINDOWS

	glfwSetTime(0.0);

#endif

	m_startTime = GetCurrentTimeMS();

	return CS_ERR_NONE;
}
intptr_t RenderThread::main() {
    RenderThreadInfo tInfo;

    //
    // initialize decoders
    //
    tInfo.m_glDec.initGL(gles1_dispatch_get_proc_func, NULL);
    tInfo.m_gl2Dec.initGL(gles2_dispatch_get_proc_func, NULL);
    initRenderControlContext(&tInfo.m_rcDec);

    ReadBuffer readBuf(m_stream, STREAM_BUFFER_SIZE);

    int stats_totalBytes = 0;
    long long stats_t0 = GetCurrentTimeMS();

    //
    // open dump file if RENDER_DUMP_DIR is defined
    //
    const char *dump_dir = getenv("RENDERER_DUMP_DIR");
    FILE *dumpFP = NULL;
    if (dump_dir) {
        size_t bsize = strlen(dump_dir) + 32;
        char *fname = new char[bsize];
        snprintf(fname,bsize,"%s/stream_%p", dump_dir, this);
        dumpFP = fopen(fname, "wb");
        if (!dumpFP) {
            fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname);
        }
        delete [] fname;
    }

    while (1) {

        int stat = readBuf.getData();
        if (stat <= 0) {
            break;
        }

        //
        // log received bandwidth statistics
        //
        stats_totalBytes += readBuf.validData();
        long long dt = GetCurrentTimeMS() - stats_t0;
        if (dt > 1000) {
            //float dts = (float)dt / 1000.0f;
            //printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
            stats_totalBytes = 0;
            stats_t0 = GetCurrentTimeMS();
        }

        //
        // dump stream to file if needed
        //
        if (dumpFP) {
            int skip = readBuf.validData() - stat;
            fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP);
            fflush(dumpFP);
        }

        bool progress;
        do {
            progress = false;

            m_lock->lock();
            //
            // try to process some of the command buffer using the GLESv1 decoder
            //
            size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the GLESv2 decoder
            //
            last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the
            // renderControl decoder
            //
            last = tInfo.m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                readBuf.consume(last);
                progress = true;
            }

            m_lock->unlock();

        } while( progress );

    }

    if (dumpFP) {
        fclose(dumpFP);
    }

    //
    // Release references to the current thread's context/surfaces if any
    //
    FrameBuffer::getFB()->bindContext(0, 0, 0);
    if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
        fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n");
    }

    FrameBuffer::getFB()->drainWindowSurface();

    FrameBuffer::getFB()->drainRenderContext();

    return 0;
}
bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock)
{
    if (needLock) m_lock.lock();
    bool ret = false;

    ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
    if (c != m_colorbuffers.end()) {

        m_lastPostedColorBuffer = p_colorbuffer;
        if (!m_subWin) {
            // no subwindow created for the FB output
            // cannot post the colorbuffer
            if (needLock) m_lock.unlock();
            return ret;
        }


        // bind the subwindow eglSurface
        if (!bindSubwin_locked()) {
            ERR("FrameBuffer::post eglMakeCurrent failed\n");
            if (needLock) m_lock.unlock();
            return false;
        }

        //
        // render the color buffer to the window
        //
        s_gl.glPushMatrix();
        s_gl.glRotatef(m_zRot, 0.0f, 0.0f, 1.0f);
        if (m_zRot != 0.0f) {
            s_gl.glClear(GL_COLOR_BUFFER_BIT);
        }
        ret = (*c).second.cb->post();
        s_gl.glPopMatrix();

        if (ret) {
            //
            // output FPS statistics
            //
            if (m_fpsStats) {
                long long currTime = GetCurrentTimeMS();
                m_statsNumFrames++;
                if (currTime - m_statsStartTime >= 1000) {
                    float dt = (float)(currTime - m_statsStartTime) / 1000.0f;
                    printf("FPS: %5.3f\n", (float)m_statsNumFrames / dt);
                    m_statsStartTime = currTime;
                    m_statsNumFrames = 0;
                }
            }

            s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
        }

        // restore previous binding
        unbind_locked();

        //
        // Send framebuffer (without FPS overlay) to callback
        //
        if (m_onPost) {
            (*c).second.cb->readback(m_fbImage);
            m_onPost(m_onPostContext, m_width, m_height, -1,
                    GL_RGBA, GL_UNSIGNED_BYTE, m_fbImage);
        }

    }

    if (needLock) m_lock.unlock();
    return ret;
}
Example #8
0
//******************************************************************************
//
//	Radio Simulator Execution Block
//
//******************************************************************************
WORD RadioSim(WORD *inBuffer, WORD *inSize, WORD *outBuffer, WORD *outSize, BYTE *BlockObjStruct)
{
	RADIO_SIM_OBJ_STRUCT *RadioSimObjStruct = (RADIO_SIM_OBJ_STRUCT *)BlockObjStruct;
	RADIO_SYSTEM *RadioSystem;
	WORD ModemIDOfInput, ModemIDOfOutput;
	WORD modemIDCounter;
	RadioSystem = RadioSimObjStruct->RadioSystem;


	if (RadioSimObjStruct->modemIDofInput == MODEM_A)
	{
		ModemIDOfInput = MODEM_A;
		ModemIDOfOutput = MODEM_B;
	}
	else
	{
		ModemIDOfOutput = MODEM_A;
		ModemIDOfInput = MODEM_B;
	}

	//
	// Checks if transition time has elapsed
	//
 	for (modemIDCounter = 0; modemIDCounter < NUM_OF_MODEM_ID; modemIDCounter++)
 	{
		if ( (GetCurrentTimeMS() - RadioSystem->ModemTransitionStartTimeMS[modemIDCounter] ) >
			RadioSystem->ModemTransitionRandomDelayMS[modemIDCounter] )
		{
			if (RadioSystem->ModemState[modemIDCounter] == MODEM_TRANSITION_TO_RECEIVE_STATE)
			{
				RadioSystem->ModemState[modemIDCounter] = MODEM_RECEIVE_STATE;
			}
			else if (RadioSystem->ModemState[modemIDCounter] == MODEM_TRANSITION_TO_TRANSMIT_STATE)
			{
				RadioSystem->ModemState[modemIDCounter] = MODEM_TRANSMIT_STATE;				
			}
			
		}
			
 	}


	if (RadioSystem->ModemState[ModemIDOfInput] ==MODEM_TRANSMIT_STATE)
	{
		//
		// Channel Open, Point-To-Point Transmission open
		//
		if (RadioSystem->ModemState[ModemIDOfOutput] == MODEM_RECEIVE_STATE)
		{
			*inSize = MIN(*inSize, *outSize);
			*outSize = *inSize;
			
			//Sets transmission for  maximum amount of data available at input and output
			memcpy(outBuffer, inBuffer, *inSize * sizeof(WORD));
		}
		//
		// Modem at Input is Transmitting, but Modem at output is not in receive mode
		//
		else
		{
			// No output from block
			*outSize = 0;
		}
	}
	else //if Modem at input is in receive state
	{
		*inSize = 0; //no data is sent from input modem
		
		//
		// Modem at output is in receive mode, but no signal is being sent by input modem
		//
		if (RadioSystem->ModemState[ModemIDOfOutput] == MODEM_RECEIVE_STATE)
		{
			if (*outSize > 0)
			{
				*outBuffer = 0;
				*outSize = 1; //one 0 word is sent to output modem
			}
		}
		//
		// Modem at output is in transmit mode
		//
		else
		{
			*outSize = 0;
		}
			
	}

	
	return 0;
}
void *RenderingThread::thread()
{

    // initialize our decoders;
    m_glDec.initGL();

#ifdef PVR_WAR
    m_glTexParameteriv = m_glDec.set_glTexParameteriv(s_glTexParameteriv);
    m_glDrawTexfOES = m_glDec.set_glDrawTexfOES(s_glDrawTexfOES);
    m_glDrawTexsOES = m_glDec.set_glDrawTexsOES(s_glDrawTexsOES);
    m_glDrawTexiOES = m_glDec.set_glDrawTexiOES(s_glDrawTexiOES);
    m_glDrawTexxOES = m_glDec.set_glDrawTexxOES(s_glDrawTexxOES);
    m_glDrawTexfvOES = m_glDec.set_glDrawTexfvOES(s_glDrawTexfvOES);
    m_glDrawTexsvOES = m_glDec.set_glDrawTexsvOES(s_glDrawTexsvOES);
    m_glDrawTexivOES = m_glDec.set_glDrawTexivOES(s_glDrawTexivOES);
    m_glDrawTexxvOES = m_glDec.set_glDrawTexxvOES(s_glDrawTexxvOES);
    m_glActiveTexture = m_glDec.set_glActiveTexture(s_glActiveTexture);
    m_glBindTexture = m_glDec.set_glBindTexture(s_glBindTexture);
    m_glEnable = m_glDec.set_glEnable(s_glEnable);
    m_glDisable = m_glDec.set_glDisable(s_glDisable);
    m_glClientActiveTexture = m_glDec.set_glClientActiveTexture(s_glClientActiveTexture);
    m_glEnableClientState = m_glDec.set_glEnableClientState(s_glEnableClientState);
    m_glDisableClientState = m_glDec.set_glDisableClientState(s_glDisableClientState);
#endif

    m_gl2Dec.initGL();

    m_utDec.set_swapBuffers(s_swapBuffers);
    m_utDec.set_createContext(s_createContext);
    m_utDec.set_destroyContext(s_destroyContext);
    m_utDec.set_createSurface(s_createSurface);
    m_utDec.set_destroySurface(s_destroySurface);
    m_utDec.set_makeCurrentContext(s_makeCurrent);

    ReadBuffer readBuf(m_stream, DECODER_BUF_SIZE);

    int stats_totalBytes = 0;
    long long stats_t0 = GetCurrentTimeMS();

    while (1) {

        int stat = readBuf.getData();
        if (stat == 0) {
            fprintf(stderr, "client shutdown\n");
            break;
        } else if (stat < 0) {
            perror("getData");
            break;
        }

        //
        // log received bandwidth statistics
        //
        stats_totalBytes += readBuf.validData();
        long long dt = GetCurrentTimeMS() - stats_t0;
        if (dt > 1000) {
            float dts = (float)dt / 1000.0f;
            printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
            stats_totalBytes = 0;
            stats_t0 = GetCurrentTimeMS();
        }

        bool progress = true;
        while (progress) {
            progress = false;
            // we need at least one header (8 bytes) in our buffer
            if (readBuf.validData() >= 8) {
                size_t last = m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
                if (last > 0) {
                    progress = true;
                    readBuf.consume(last);
                }
            }

            if (readBuf.validData() >= 8) {
                size_t last = m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
                if (last > 0) {
                    readBuf.consume(last);
                    progress = true;
                }
            }

            if (readBuf.validData() >= 8) {
                size_t last = m_utDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
                if (last > 0) {
                    readBuf.consume(last);
                    progress = true;
                }
            }
        }
    }
    // shutdown
    if (m_currentContext != NULL) {
        m_currentContext->unref();
    }

    return NULL;
}
Example #10
0
//******************************************************************************
//
//	Tx Gate Execution Block
//
//******************************************************************************
WORD TxGate(WORD *inBuffer, WORD *inSize, WORD *outBuffer, WORD *outSize, BYTE *BlockObjStruct)
{
	TXRX_GATES_OBJ_STRUCT * GateObjStruct = (TXRX_GATES_OBJ_STRUCT *)BlockObjStruct;

//#ifdef DEBUG_TXGATE
       if (CurrentControllerPtr->optionFlags & CONTROLLER_OPTIONS_PRINT_DEBUG)
       {
        	if (GateObjStruct->prevState != GateObjStruct->currentState)
        	{
//                    if (GateObjStruct->currentState == GATE_TRANSMIT_STATE)
//                    {
                        DebugMsgW("\n\rGate State = %d - ", (WORD)GateObjStruct->currentState);
                        DebugMsg(CurrentControllerPtr->nameString);
                        DebugMsgDW(" @%lu", GetCurrentTimeMS() );
//                    }
                    GateObjStruct->prevState = GateObjStruct->currentState;
        	}

       }

//#endif

    TxLEDStatus(GateObjStruct->currentState);

	switch (GateObjStruct->currentState)
	{
		case (GATE_TRANS_TO_RECEIVE_STATE):
		case (GATE_RECEIVE_STATE):
		{			
			//Input detected, switch to transmit
			if (*inSize >0)
			{
#ifdef PLATFORM_SIM				
				RadioSimStartTx(GateObjStruct->modemID);
#endif
#ifdef PLATFORM_HW
				HwGpioSetPTT(TRUE);
#endif
				GateObjStruct->currentState = GATE_TRANS_TO_TRANSMIT_STATE;
				GateObjStruct->transitionStartTimeMS = GetCurrentTimeMS();
			}


			break;
		}
		case (GATE_TRANS_TO_TRANSMIT_STATE):
		{
			if ((GetCurrentTimeMS() - GateObjStruct->transitionStartTimeMS) > 
				TXGATE_TRANSITION_TO_TRANSMIT_WAIT_MS && *outSize >= 8 )
			{
				GateObjStruct->currentState = GATE_TRANSMIT_STATE;
				//
				// Inserts empty word at beginning of transmission
				//
                *inSize = 0;
				*outSize = 8;
                *outBuffer++ = 45295;
                *outBuffer++ = 60807;
                *outBuffer++ = 26305;       
                *outBuffer++ = 46268;
                *outBuffer++ = 45295;
                *outBuffer++ = 60807;
                *outBuffer++ = 45295;
                *outBuffer++ = 60807;

                return RETURN_OK;
			}

			break;
		}			
		case (GATE_TRANSMIT_STATE):
		{
			
			if (*inSize > 0)
			{
				*inSize = MIN(*inSize, *outSize);
				*outSize = *inSize;
				
				memcpy(outBuffer, inBuffer, *inSize * sizeof(WORD));
				
				return RETURN_OK;
			}
			//
			// No data at input
			//
			else
			{
				if (IsCurrentPipelineIdle() && IsCurrentPipelineEmptyDownStream())
				{
					if ( (GateObjStruct->transmitPipelineIdleHysterisis++) > TXGATE_TRANSMIT_PIPELINE_IDLE_HYSTERISIS )
					{
						//
						// Inserts empty word at end of transmission
						//
						*outSize = 1;
						*outBuffer = 0;
						
						GateObjStruct->transmitPipelineIdleHysterisis = 0;
						GateObjStruct->currentState = GATE_TRANSMIT_END_STATE;

						return RETURN_OK;
					}
				}

			}
			break;
		}
		case (GATE_TRANSMIT_END_STATE):
		{
			if (IsCurrentPipelineEmptyDownStream())
			{
				GateObjStruct->transitionStartTimeMS = GetCurrentTimeMS();
				GateObjStruct->currentState = GATE_WAIT_TO_TURN_RECEIVE_ON_STATE;
			}
			break;
		}

	}

	return RETURN_CONTROLLER_BLOCK_IDLE;
}
Example #11
0
//******************************************************************************
//
// FUNCTION:        getTimeCmdAction
//
// USAGE:             return the current timer information
//
//******************************************************************************
void getTimeCmdAction(SDWORD parameters[])
{
	DebugMsgDW("\n\rCurrent Time %lu", GetCurrentTimeMS());

	
}
Example #12
0
int RenderThread::Main()
{
    RenderThreadInfo * tInfo = getRenderThreadInfo();
    //
    // initialize decoders
    //
    tInfo->m_glDec.initGL( gl_dispatch_get_proc_func, NULL );
    tInfo->m_gl2Dec.initGL( gl2_dispatch_get_proc_func, NULL );
    initRenderControlContext( &m_rcDec );

    ReadBuffer readBuf(m_stream, STREAM_BUFFER_SIZE);

    int stats_totalBytes = 0;
    long long stats_t0 = GetCurrentTimeMS();

    //
    // open dump file if RENDER_DUMP_DIR is defined
    //
    const char *dump_dir = getenv("RENDERER_DUMP_DIR");
    FILE *dumpFP = NULL;
    if (dump_dir) {
        size_t bsize = strlen(dump_dir) + 32;
        char *fname = new char[bsize];
        snprintf(fname,bsize,"%s/stream_%p", dump_dir, this);
        dumpFP = fopen(fname, "wb");
        if (!dumpFP) {
            fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname);
        }
        delete [] fname;
    }

    while (1) {

        int stat = readBuf.getData();
        if (stat <= 0) {
            break;
        }

        //
        // log received bandwidth statistics
        //
        stats_totalBytes += readBuf.validData();
        long long dt = GetCurrentTimeMS() - stats_t0;
        if (dt > 1000) {
            float dts = (float)dt / 1000.0f;
            //printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
            stats_totalBytes = 0;
            stats_t0 = GetCurrentTimeMS();
        }

        //
        // dump stream to file if needed
        //
        if (dumpFP) {
            int skip = readBuf.validData() - stat;
            fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP);
            fflush(dumpFP);
        }

        bool progress;
        do {
            progress = false;

            //
            // try to process some of the command buffer using the GLESv1 decoder
            //
            size_t last = tInfo->m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the GLESv2 decoder
            //
            last = tInfo->m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                progress = true;
                readBuf.consume(last);
            }

            //
            // try to process some of the command buffer using the
            // renderControl decoder
            //
            last = m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
            if (last > 0) {
                readBuf.consume(last);
                progress = true;
            }

        } while( progress );

    }

    if (dumpFP) {
        fclose(dumpFP);
    }

    //
    // release the thread from any EGL context
    // if bound to context.
    //
    EGLDisplay eglDpy = s_egl.eglGetCurrentDisplay();
    if (eglDpy != EGL_NO_DISPLAY) {
        s_egl.eglMakeCurrent(eglDpy,
                             EGL_NO_SURFACE,
                             EGL_NO_SURFACE,
                             EGL_NO_CONTEXT);
    }

    //
    // flag that this thread has finished execution
    m_finished = true;

    return 0;
}
Example #13
0
bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock)
{
    if (needLock) {
        m_lock.lock();
    }
    bool ret = false;

    ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
    if (c == m_colorbuffers.end()) {
        goto EXIT;
    }

    m_lastPostedColorBuffer = p_colorbuffer;

    if (m_subWin) {
        // bind the subwindow eglSurface
        if (!bindSubwin_locked()) {
            ERR("FrameBuffer::post(): eglMakeCurrent failed\n");
            goto EXIT;
        }

        //
        // render the color buffer to the window
        //
        if (m_zRot != 0.0f) {
            s_gles2.glClear(GL_COLOR_BUFFER_BIT);
        }
        ret = (*c).second.cb->post(m_zRot);
        if (ret) {
            s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
        }

        // restore previous binding
        unbind_locked();
    } else {
        // If there is no sub-window, don't display anything, the client will
        // rely on m_onPost to get the pixels instead.
        ret = true;
    }

    //
    // output FPS statistics
    //
    if (m_fpsStats) {
        long long currTime = GetCurrentTimeMS();
        m_statsNumFrames++;
        if (currTime - m_statsStartTime >= 1000) {
            float dt = (float)(currTime - m_statsStartTime) / 1000.0f;
            printf("FPS: %5.3f\n", (float)m_statsNumFrames / dt);
            m_statsStartTime = currTime;
            m_statsNumFrames = 0;
        }
    }

    //
    // Send framebuffer (without FPS overlay) to callback
    //
    if (m_onPost) {
        (*c).second.cb->readback(m_fbImage);
        m_onPost(m_onPostContext,
                 m_width,
                 m_height,
                 -1,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 m_fbImage);
    }

EXIT:
    if (needLock) {
        m_lock.unlock();
    }
    return ret;
}