Пример #1
0
EIO_Status CConn_FtpStream::Drain(const STimeout* timeout)
{
    const STimeout* r_timeout = kInfiniteTimeout/*0*/;
    const STimeout* w_timeout = kInfiniteTimeout/*0*/;
    CONN conn = GetCONN();
    char block[1024];
    if (conn) {
        size_t n;
        r_timeout = CONN_GetTimeout(conn, eIO_Read);
        w_timeout = CONN_GetTimeout(conn, eIO_Write);
        _VERIFY(SetTimeout(eIO_Read,  timeout) == eIO_Success);
        _VERIFY(SetTimeout(eIO_Write, timeout) == eIO_Success);
        // Cause any upload-in-progress to abort
        CONN_Read (conn, block, sizeof(block), &n, eIO_ReadPlain);
        // Cause any command-in-progress to abort
        CONN_Write(conn, "NOOP\n", 5, &n, eIO_WritePersist);
    }
    clear();
    while (read(block, sizeof(block)))
        ;
    if (!conn)
        return eIO_Closed;
    EIO_Status status;
    do {
        size_t n;
        status = CONN_Read(conn, block, sizeof(block), &n, eIO_ReadPersist);
    } while (status == eIO_Success);
    _VERIFY(CONN_SetTimeout(conn, eIO_Read,  r_timeout) == eIO_Success);
    _VERIFY(CONN_SetTimeout(conn, eIO_Write, w_timeout) == eIO_Success);
    clear();
    return status == eIO_Closed ? eIO_Success : status;
}
Пример #2
0
void CConn_Streambuf::x_Init(const STimeout* timeout, size_t buf_size,
                             CConn_IOStream::TConn_Flags flags,
                             CT_CHAR_TYPE* ptr, size_t size)
{
    _ASSERT(m_Status == eIO_Success);

    if (timeout != kDefaultTimeout) {
        _VERIFY(CONN_SetTimeout(m_Conn, eIO_Open,      timeout) ==eIO_Success);
        _VERIFY(CONN_SetTimeout(m_Conn, eIO_ReadWrite, timeout) ==eIO_Success);
        _VERIFY(CONN_SetTimeout(m_Conn, eIO_Close,     timeout) ==eIO_Success);
    }

    if (!(flags & (CConn_IOStream::fConn_ReadBuffered |
                   CConn_IOStream::fConn_WriteBuffered))) {
        buf_size = 0;
    }
    if (buf_size) {
        m_WriteBuf = new
            CT_CHAR_TYPE[buf_size
                         << ((flags & (CConn_IOStream::fConn_ReadBuffered |
                                       CConn_IOStream::fConn_WriteBuffered))
                             ==       (CConn_IOStream::fConn_ReadBuffered |
                                       CConn_IOStream::fConn_WriteBuffered)
                             ? 1 : 0)];
        if (flags & CConn_IOStream::fConn_ReadBuffered)
            m_BufSize = buf_size;
        if (!(flags & CConn_IOStream::fConn_WriteBuffered))
            buf_size = 0;
        if (flags & CConn_IOStream::fConn_ReadBuffered)
            m_ReadBuf = m_WriteBuf + buf_size;
    } /* else see ctor */

    if (buf_size)
        setp(m_WriteBuf, m_WriteBuf + buf_size);
    /* else setp(0, 0) */
    if (ptr)
        setg(ptr,        ptr,       ptr + size);   // Initial get area
    else
        setg(m_ReadBuf,  m_ReadBuf, m_ReadBuf);    // Empty get area

    SCONN_Callback cb;
    cb.func = x_OnClose; /* NCBI_FAKE_WARNING: WorkShop */
    cb.data = this;
    CONN_SetCallback(m_Conn, eCONN_OnClose, &cb, &m_Cb);
    m_CbValid = true;
}
static int idaapi init(void)
{
    msg("\nLoadMap: Plugin init.\n\n");

    // Get the full path of plugin
    WIN32CHECK(GetModuleFileName(g_hinstPlugin, g_szIniPath, sizeof(g_szIniPath)));
    g_szIniPath[sizeof(g_szIniPath) - 1] = '\0';

    // Change the extension of plugin to '.ini'
    _VERIFY(PathRenameExtension(g_szIniPath, ".ini"));

    // Get options saved in ini file
    _VERIFY(GetPrivateProfileStruct(g_szLoadMapSection, g_szOptionsKey,
                                    &g_options, sizeof(g_options), g_szIniPath));

    return PLUGIN_KEEP;
}
static void idaapi term(void)
{
    msg("LoadMap: Plugin terminate.\n");

    // Write the plugin's options to ini file
    _VERIFY(WritePrivateProfileStruct(g_szLoadMapSection, g_szOptionsKey, &g_options,
                                      sizeof(g_options), g_szIniPath));
}
Пример #5
0
void CMutexPool::SetSize(int size)
{
    _VERIFY(m_size==0 && !m_Locks);
    m_size = size;
    m_Locks = new CMutex[m_size];
    spread  = new int[m_size];
    for ( int i = 0; i < m_size; ++i ) {
        spread[i]=0;
    }
}
Пример #6
0
static
TLastNewPtrMultiple& sx_GetLastNewPtrMultiple(void)
{
#ifdef NCBI_NO_THREADS
    return s_LastNewPtrMultiple;
#else
    if ( !s_LastNewPtrMultiple_key ) {
        DEFINE_STATIC_FAST_MUTEX(s_InitMutex);
        NCBI_NS_NCBI::CFastMutexGuard guard(s_InitMutex);
        if ( !s_LastNewPtrMultiple_key ) {
            TTlsKey key = 0;
            do {
#  ifdef NCBI_WIN32_THREADS
                _VERIFY((key = TlsAlloc()) != DWORD(-1));
#  else
                _VERIFY(pthread_key_create(&key, sx_EraseLastNewPtrMultiple)==0);
#  endif
            } while ( !key );
#  ifndef NCBI_WIN32_THREADS
            pthread_setspecific(key, 0);
#  endif
            s_LastNewPtrMultiple_key = key;
        }
    }
    TLastNewPtrMultiple* set;
#  ifdef NCBI_WIN32_THREADS
    set = (TLastNewPtrMultiple*)TlsGetValue(s_LastNewPtrMultiple_key);
#  else
    set = (TLastNewPtrMultiple*)pthread_getspecific(s_LastNewPtrMultiple_key);
#  endif
    if ( !set ) {
        set = new TLastNewPtrMultiple();
#  ifdef NCBI_WIN32_THREADS
        TlsSetValue(s_LastNewPtrMultiple_key, set);
#  else
        pthread_setspecific(s_LastNewPtrMultiple_key, set);
#  endif
    }
    return *set;
#endif
}
Пример #7
0
CGBLGuard::CGBLGuard(CGBLGuard &g,const char *loc)
    : m_Locks(g.m_Locks),
      m_Loc(g.m_Loc),
      m_orig(g.m_current),
      m_current(g.m_current),
      m_select(g.m_select)
{
    if ( loc ) {
        m_Loc = loc;
    }
    _VERIFY(m_Locks);
}
Пример #8
0
static VOID CdiagsDereferenceFormatter(
    __in PCDIAG_FORMATTER This
)
{
    PCDIAGP_FORMATTER Formatter = ( PCDIAGP_FORMATTER ) This;

    _ASSERTE( CdiagsIsValidFormatter( Formatter ) );

    if ( 0 == InterlockedDecrement( &Formatter->ReferenceCount ) )
    {
        _VERIFY( S_OK == CdiagsDeleteFormatter( Formatter ) );
    }
}
	int VideoEncoderFfmpeg::Encode(int force_key_frame, int *is_key_frame)
	{
		if (bitrate() < 0)
			return 0;
		
		frag_writer()->Clear();
		frame_->pict_type = AV_PICTURE_TYPE_NONE != force_key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
		int enc_size = avcodec_encode_video(context_,
			output_buffer(), output_buffer_size(), frame_);
		if (0 == enc_size)
			return 0;

		if (NULL != is_key_frame)
			*is_key_frame = frame_->key_frame;

		int size = 0;

		Fragmenter *fragmenter = GetFragmenter();
		if (fragsize() > 0 && NULL != fragmenter) {
#ifdef FRAG_FILE_DEBUG
			{
				static int frame_count_enc = 0;
				FILE *fd = NULL;
				char filename[50];
				sprintf_s(filename, "out_enc_%03d.dbg", frame_count_enc);
				_VERIFY(0 == fopen_s(&fd, filename, "wb"));
				fwrite(output_buffer(), enc_size, 1, fd);
				fclose(fd);
				++frame_count_enc;
			}
#endif
			size = fragmenter->Fragment(output_buffer(), enc_size);
		} else {
			size = enc_size;
			_VERIFY(frag_writer()->AppendItem(output_buffer(), enc_size));
		}
		*fragcount() = frag_writer()->frag_count();
		return size;
	}
Пример #10
0
void CInterProcessLock::Unlock()
{
    if (m_Handle == kInvalidLockHandle) {
        NCBI_THROW(CInterProcessLockException, eNotLocked,
                   "Attempt to unlock not-yet-acquired lock");
    }
    CFastMutexGuard LOCK(s_ProcessLock);

    // Check that lock with specified name not already locked
    // in the current process.
    TLocks::iterator it = s_Locks->find(m_SystemName);
    _VERIFY(it != s_Locks->end());

    if ( it->second > 1 ) {
        // Just decrease reference counter
        it->second--;
        return;
    }

    // Release lock

#if defined(NCBI_OS_UNIX)

#  if defined(F_TLOCK)
    int res = lockf(m_Handle, F_ULOCK, 0);
#  elif defined(F_SETLK)
    struct flock lockparam;
    lockparam.l_type   = F_UNLCK;
    lockparam.l_whence = SEEK_SET;
    lockparam.l_start  = 0;
    lockparam.l_len    = 0;  /* whole file */
    int res = fcntl(m_Handle, F_SETLK, &lockparam);
#  else
#   error "No supported lock method.  Please port this code."
#  endif
    if ( res < 0 ) {
        NCBI_THROW(CInterProcessLockException, eUnlockError,
                   "Cannot release the lock");
    }
    close(m_Handle);
    
#elif defined(NCBI_OS_MSWIN)
    if ( !::ReleaseMutex(m_Handle) ) {
        NCBI_THROW(CInterProcessLockException, eUnlockError,
                   "Cannot release the lock");
    }
    ::CloseHandle(m_Handle);
#endif
    m_Handle = kInvalidLockHandle;
    s_Locks->erase(m_SystemName);
}
Пример #11
0
_f_int _F90_VERIFY( char    *str1,
	            char    *str2,
	            _f_int  *back,
	            _f_int  len1,
	            _f_int  len2 )
{
    fcd_t  fcd1, fcd2;

    fcd1.ptr = str1;
    fcd1.len = len1;
    fcd2.ptr = str2;
    fcd2.len = len2;
    
    return( _VERIFY( fcd1, fcd2, back ) );
}
Пример #12
0
void CDelayBuffer::DoUpdate(void)
{
    _ASSERT(m_Info.get() != 0);
    SInfo& info = *m_Info;

    {
        auto_ptr<CObjectIStream> in(CObjectIStream::Create(info.m_DataFormat,
                                                           *info.m_Source));
        in->SetFlags(info.m_Flags);
        info.m_ItemInfo->UpdateDelayedBuffer(*in, info.m_Object);
        _VERIFY(in->EndOfData());
    }

    m_Info.reset(0);
}
Пример #13
0
void check_cnts(size_t expected = 0,
                size_t expected_static = 0)
{
    if ( expected == ~0u ) {
        expected = 0;
    }
    else {
        expected = 1;
    }
    if ( expected == 0 ) {
        if ( alloc_count.Get() != expected-expected_static )
            ERR_FATAL("alloc_count: "<<alloc_count.Get());
        if ( object_count.Get() != expected )
            ERR_FATAL("object_count: "<<object_count.Get());
    }
    _VERIFY(!sx_HaveLastNewPtr());
}
Пример #14
0
streamsize CConn_Streambuf::showmanyc(void)
{
    static const STimeout kZeroTmo = {0, 0};

    _ASSERT(gptr() >= egptr());

    if (!m_Conn)
        return -1L;

    // flush output buffer, if tied up to it
    if (m_Tie)
        x_sync();

    const STimeout* tmo;
    const STimeout* timeout = CONN_GetTimeout(m_Conn, eIO_Read);
    if (timeout == kDefaultTimeout) {
        // HACK * HACK * HACK
        tmo = ((SMetaConnector*) m_Conn)->default_timeout;
    } else
        tmo = timeout;

    size_t x_read;
    bool backup = false;
    if (m_BufSize > 1) {
        if (eback() < gptr()) {
            x_Buf = gptr()[-1];
            backup = true;
        }
        if (!tmo)
            _VERIFY(CONN_SetTimeout(m_Conn, eIO_Read, &kZeroTmo)==eIO_Success);
        m_Status = CONN_Read(m_Conn, m_ReadBuf + 1, m_BufSize - 1,
                             &x_read, eIO_ReadPlain);
        if (!tmo)
            _VERIFY(CONN_SetTimeout(m_Conn, eIO_Read, timeout)  ==eIO_Success);
        _ASSERT(x_read > 0  ||  m_Status != eIO_Success);
    } else {
        m_Status = CONN_Wait(m_Conn, eIO_Read, tmo ? tmo : &kZeroTmo);
        x_read = 0;
    }

    if (!x_read) {
        switch (m_Status) {
        case eIO_Success:
            _ASSERT(m_BufSize <= 1);
            return  1L;  // can read at least 1 byte
        case eIO_Timeout:
            if (!tmo  ||  !(tmo->sec | tmo->usec))
                break;
            /*FALLTHRU*/
        case eIO_Closed:
            return -1L;  // EOF
        default:
            break;
        }
        return       0;  // no data available immediately
    }

    m_ReadBuf[0] = x_Buf;
    _ASSERT(m_BufSize > 1);
    setg(m_ReadBuf + !backup, m_ReadBuf + 1, m_ReadBuf + 1 + x_read);
    x_GPos += x_read;
    return x_read;
}
Пример #15
0
int CCompressionStreambuf::Flush(CCompressionStream::EDirection dir)
{
    CSP* sp = GetStreamProcessor(dir);

    // Check processor's status
    if ( sp->m_LastStatus == CP::eStatus_Error ) {
        return -1;
    }
    if ( sp->m_LastStatus == CP::eStatus_EndOfData ) {
        // Flush underlying stream (on write)
        if (dir == CCompressionStream::eWrite  &&  
            !WriteOutBufToStream(true /*force write*/)) {
            return -1;
        }
        // End of data, nothing to do
        return 0;
    }

    // Flush stream compressor
    CT_CHAR_TYPE* buf = 0;
    size_t out_size = 0, out_avail = 0;
    do {
        // Get pointer to the free space in the buffer
        if ( dir == CCompressionStream::eRead ) {
            buf = egptr();
        } else {
            buf = sp->m_End;
        }
        out_size = sp->m_OutBuf + sp->m_OutBufSize - buf;

        // Get data from processor
        out_avail = 0;
        if ( sp->m_State == CSP::eFinalize ) {
            // State is eFinalize
            sp->m_LastStatus = 
                sp->m_Processor->Finish(buf, out_size, &out_avail);
        } else {
            // State is eActive
            _VERIFY(sp->m_State == CSP::eActive);
            sp->m_LastStatus = 
                sp->m_Processor->Flush(buf, out_size, &out_avail);
            // No more data -- automaticaly finalize stream
            if ( sp->m_LastStatus == CP::eStatus_EndOfData ) {
                sp->m_State = CSP::eFinalize;
            }
        } 
        // Check on error
        if ( sp->m_LastStatus == CP::eStatus_Error ) {
            return -1;
        }
        if ( dir == CCompressionStream::eRead ) {
            // Update the get's pointers
            setg(sp->m_OutBuf, gptr(), egptr() + out_avail);
        } else { // CCompressionStream::eWrite
            // Update the output buffer pointer
            sp->m_End += out_avail;
            // Write data to the underlying stream only if the output buffer
            // is full or an overflow/endofdata occurs.
            if ( !WriteOutBufToStream() ) {
                return -1;
            }
        }
    } while (sp->m_LastStatus == CP::eStatus_Repeat  ||
            (out_avail  &&  (sp->m_LastStatus == CP::eStatus_Success || 
                             sp->m_LastStatus == CP::eStatus_Overflow))
            );

    // Flush underlying stream (on write)
    if (dir == CCompressionStream::eWrite) {
        if ( sp->m_LastStatus == CP::eStatus_EndOfData  ||
             sp->m_State == CSP::eFinalize) {
            if ( !WriteOutBufToStream(true /*force write*/) ) {
                return -1;
            }
        }
    }
    return 0;
}
Пример #16
0
void CId2Reader::x_RemoveConnectionSlot(TConn conn)
{
    _VERIFY(m_Connections.erase(conn));
}
Пример #17
0
void CInterProcessLock::Lock(const CTimeout& timeout,
                             const CTimeout& granularity)
{
    CFastMutexGuard LOCK(s_ProcessLock);

    // Check that lock with specified name not already locked
    // in the current process.
    TLocks::iterator it = s_Locks->find(m_SystemName);

    if (m_Handle != kInvalidLockHandle) {
        // The lock is already set in this CInterProcessLock object,
        // just increase reference counter.
        _VERIFY(it != s_Locks->end());
        it->second++;
        return;
    } else {
        if (it != s_Locks->end()) {
            // The lock already exists in the current process.
            // We can use one CInterProcessLock object with
            // multiple Lock() calls, but not with different
            // CInterProcessLock objects. For example, on MS-Windows,
            // we cannot wait on the same mutex in the same thread.
            // So, two different objects can set locks simultaneously.
            // And for OS-compatibility we can do nothing here,
            // except throwing an exception.
            NCBI_THROW(CInterProcessLockException, eMultipleLocks,
                       "Attempt to lock already locked object " \
                       "in the same process");
        }
    }

    // Try to acquire a lock with specified timeout

#if defined(NCBI_OS_UNIX)

    // Open lock file
    mode_t perm = CDirEntry::MakeModeT(
        CDirEntry::fRead | CDirEntry::fWrite /* user */,
        CDirEntry::fRead | CDirEntry::fWrite /* group */,
        0, 0 /* other & special */);
    int fd = open(m_SystemName.c_str(), O_CREAT | O_RDWR, perm);
    if (fd == -1) {
        NCBI_THROW(CInterProcessLockException, eCreateError,
                   string("Error creating lockfile ") + m_SystemName + 
                   ": " + strerror(errno));
    }

    // Try to acquire the lock
    
    int x_errno = 0;
    
    if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
        while ((x_errno = s_UnixLock(fd))) {
            if (errno != EAGAIN)
                break;
        }

    } else {
        unsigned long ms = timeout.GetAsMilliSeconds();
        if ( !ms ) {
            // Timeout == 0
            x_errno = s_UnixLock(fd);
        } else {
            // Timeout > 0
            unsigned long ms_gran;
            if ( granularity.IsInfinite()  ||
                 granularity.IsDefault() ) 
            {
                ms_gran = min(ms/5, (unsigned long)500);
            } else {
                ms_gran = granularity.GetAsMilliSeconds();
            }
            // Try to lock within specified timeout
            for (;;) {
                x_errno = s_UnixLock(fd);
                if ( !x_errno ) {
                    // Successfully locked
                    break;
                }
                if (x_errno != EACCES  &&
                    x_errno != EAGAIN ) {
                    // Error
                    break;
                }
                // Otherwise -- sleep granularity timeout
                unsigned long ms_sleep = ms_gran;
                if (ms_sleep > ms) {
                    ms_sleep = ms;
                }
                if ( !ms_sleep ) {
                     break;
                }
                SleepMilliSec(ms_sleep);
                ms -= ms_sleep;
            }
            // Timeout
            if ( !ms ) {
                close(fd);
                NCBI_THROW(CInterProcessLockException, eLockTimeout,
                           "The lock could not be acquired in the time " \
                           "allotted");
            }
        } // if (!ms)
    } // if (timeout.IsInfinite())
    
    // Error
    if ( x_errno ) {
        close(fd);
        NCBI_THROW(CInterProcessLockException, eLockError,
                   "Error creating lock");
    }
    // Success
    m_Handle = fd;

#elif defined(NCBI_OS_MSWIN)

    HANDLE  handle  = ::CreateMutex(NULL, TRUE, _T_XCSTRING(m_SystemName));
    errno_t errcode = ::GetLastError();
    if (handle == kInvalidLockHandle) {
        switch(errcode) {
            case ERROR_ACCESS_DENIED:
                // Mutex with specified name already exists, 
                // but we don't have enough rights to open it.
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "The lock already exists");
                break;
            case ERROR_INVALID_HANDLE:
                // Some system object with the same name already exists
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "Error creating lock, system object with the same" \
                           "name already exists");
                break;
            default:
                // Unknown error
                NCBI_THROW(CInterProcessLockException, eCreateError,
                           "Error creating lock");
                break;
        }
    } else {
        // Mutex with specified name already exists
        if (errcode == ERROR_ALREADY_EXISTS) {
            // Wait
            DWORD res;
            if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
                res = WaitForSingleObject(handle, INFINITE);
            } else {
                res = WaitForSingleObject(handle, timeout.GetAsMilliSeconds());
            }
            switch(res) {
                case WAIT_OBJECT_0:
                    // The lock has been acquired
                    break;
                case WAIT_TIMEOUT:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockTimeout,
                               "The lock could not be acquired in the time " \
                               "allotted");
                    break;
                case WAIT_ABANDONED:
                    // The lock is in abandoned state... Other thread/process
                    // owning it was terminated. We can reuse this mutex, but 
                    // it is better to wait until it will be released by OS.
                    /* FALLTHRU */
                default:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockError,
                               "Error creating lock");
                    break;
            }
        }
        m_Handle = handle;
    }
#endif
    // Set reference counter to 1
    (*s_Locks)[m_SystemName] = 1;
}
Пример #18
0
void CTestTlsObjectApp::RunTest(void)
{
    const size_t OBJECT_SIZE = sizeof(CObjectWithNew);
    for ( int t = 0; t < 1; ++t ) {
        // prealloc
        {
            size_t size = (OBJECT_SIZE+16)*COUNT;
            void* p = ::operator new(size);
            memset(p, 1, size);
            ::operator delete(p);
        }
        {
            const size_t COUNT2 = COUNT*2;
            void** p = new void*[COUNT2];
            for ( size_t i = 0; i < COUNT2; ++i ) {
                add_alloc(1);
                add_step();
                p[i] = ::operator new(OBJECT_SIZE);
            }
            for ( size_t i = 0; i < COUNT2; ++i ) {
                add_alloc(-1);
                add_step();
                ::operator delete(p[i]);
            }
            delete[] p;
        }
        {
            const size_t COUNT2 = COUNT*2;
            int** p = new int*[COUNT2];
            for ( size_t i = 0; i < COUNT2; ++i ) {
                add_alloc(1);
                add_step();
                p[i] = new int(int(i));
            }
            for ( size_t i = 0; i < COUNT2; ++i ) {
                add_alloc(-1);
                add_step();
                delete p[i];
            }
            delete[] p;
        }
    }
    //return;
    CStopWatch sw;
    check_cnts();
    for ( int t = 0; t < 1; ++t ) {
        void** ptr = new void*[COUNT];
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_alloc(1);
            add_step();
            ptr[i] = ::operator new(OBJECT_SIZE);
        }
        double t1 = sw.Elapsed();
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_alloc(-1);
            add_step();
            ::operator delete(ptr[i]);
        }
        double t2 = sw.Elapsed();
        message("plain malloc", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        sw.Start();
        int* ptr = new int;
        sx_PushLastNewPtr(ptr, 2);
        double t1 = sw.Elapsed();
        sw.Start();
        _VERIFY(sx_PopLastNewPtr(ptr));
        delete ptr;
        double t2 = sw.Elapsed();
        message("tls", "set", t1, "get", t2, COUNT);
    }
    check_cnts();
    {
        CObjectWithNew** ptr = new CObjectWithNew*[COUNT];
        for ( size_t i = 0; i < COUNT; ++i ) {
            ptr[i] = 0;
        }
        sw.Start();
        s_CurrentStep = "new CObjectWithNew";
        s_CurrentInHeap = true;
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            ptr[i] = new CObjectWithNew;
        }
        s_CurrentInHeap = false;
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        for ( size_t i = 0; i < COUNT; ++i ) {
            _ASSERT(ptr[i]->IsInHeap());
        }
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            CObjectWithNew::Delete(ptr[i]);
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithNew", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        CObjectWithTLS** ptr = new CObjectWithTLS*[COUNT];
        sw.Start();
        s_CurrentStep = "new CObjectWithTLS";
        s_CurrentInHeap = true;
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            try {
                switch ( rand()%3 ) {
                case 0: ptr[i] = new CObjectWithTLS; break;
                case 1: ptr[i] = new CObjectWithTLS2; break;
                case 2: ptr[i] = new CObjectWithTLS3; break;
                }
            }
            catch ( exception& ) {
                ptr[i] = 0;
            }
            _ASSERT(!sx_HaveLastNewPtr());
            _ASSERT(!ptr[i] || ptr[i]->IsInHeap());
        }
        s_CurrentInHeap = false;
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            CObjectWithTLS::Delete(ptr[i]);
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithTLS", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        CRef<CObjectWithRef>* ptr = new CRef<CObjectWithRef>[COUNT];
        sw.Start();
        s_CurrentStep = "new CObjectWithRef";
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            try {
                switch ( rand()%2 ) {
                case 0: ptr[i] = new CObjectWithRef; break;
                case 1: ptr[i] = new CObjectWithRef2; break;
                }
            }
            catch ( exception& ) {
                ptr[i] = 0;
            }
            _ASSERT(!sx_HaveLastNewPtr());
            _ASSERT(!ptr[i] || ptr[i]->CanBeDeleted());
        }
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            ptr[i].Reset();
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithRef", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        CObjectWithNew** ptr = new CObjectWithNew*[COUNT];
        for ( size_t i = 0; i < COUNT; ++i ) {
            ptr[i] = 0;
        }
        sw.Start();
        s_CurrentStep = "new CObjectWithNew()";
        s_CurrentInHeap = true;
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            ptr[i] = new CObjectWithNew();
        }
        s_CurrentInHeap = false;
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        for ( size_t i = 0; i < COUNT; ++i ) {
            _ASSERT(ptr[i]->IsInHeap());
        }
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            CObjectWithNew::Delete(ptr[i]);
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithNew()", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        CObjectWithTLS** ptr = new CObjectWithTLS*[COUNT];
        sw.Start();
        s_CurrentStep = "new CObjectWithTLS()";
        s_CurrentInHeap = true;
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            try {
                switch ( rand()%4 ) {
                case 0: ptr[i] = new CObjectWithTLS(); break;
                case 1: ptr[i] = new CObjectWithTLS2(); break;
                case 2: ptr[i] = new CObjectWithTLS3(); break;
                case 3: ptr[i] = new CObjectWithTLS3(RecursiveNewTLS(rand()%4)); break;
                }
            }
            catch ( exception& ) {
                ptr[i] = 0;
            }
            _ASSERT(!sx_HaveLastNewPtr());
            _ASSERT(!ptr[i] || ptr[i]->IsInHeap());
        }
        s_CurrentInHeap = false;
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            CObjectWithTLS::Delete(ptr[i]);
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithTLS()", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        CRef<CObjectWithRef>* ptr = new CRef<CObjectWithRef>[COUNT];
        sw.Start();
        s_CurrentStep = "new CObjectWithRef()";
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            try {
                size_t j = rand()%COUNT;
                switch ( rand()%4 ) {
                case 0: ptr[j] = new CObjectWithRef(); break;
                case 1: ptr[j] = new CObjectWithRef(RecursiveNewRef(rand()%4)); break;
                case 2: ptr[j] = new CObjectWithRef2(); break;
                case 3: ptr[j] = new CObjectWithRef2(RecursiveNewRef(rand()%4)); break;
                }
            }
            catch ( exception& ) {
                ptr[i] = 0;
            }
            _ASSERT(!sx_HaveLastNewPtr());
            _ASSERT(!ptr[i] || ptr[i]->CanBeDeleted());
        }
        double t1 = sw.Elapsed();
        check_cnts(COUNT);
        sw.Start();
        for ( size_t i = 0; i < COUNT; ++i ) {
            add_step();
            ptr[i] = 0;
        }
        double t2 = sw.Elapsed();
        message("new CObjectWithRef()", "create", t1, "delete", t2, COUNT);
        delete[] ptr;
    }
    check_cnts();
    {
        sw.Start();
        s_CurrentStep = "CObjectWithNew[]";
        CArray<CObjectWithNew, COUNT>* arr =
            new CArray<CObjectWithNew, COUNT>;
        double t1 = sw.Elapsed();
        check_cnts(COUNT, COUNT);
        for ( size_t i = 0; i < COUNT; ++i ) {
            _ASSERT(!arr->m_Array[i].IsInHeap());
        }
        sw.Start();
        delete arr;
        double t2 = sw.Elapsed();
        message("static CObjectWithNew", "create", t1, "delete", t2, COUNT);
    }
    check_cnts();
    {
        sw.Start();
        s_CurrentStep = "CObjectWithTLS[]";
        CArray<CObjectWithTLS, COUNT, false>* arr =
            new CArray<CObjectWithTLS, COUNT, false>;
        double t1 = sw.Elapsed();
        check_cnts(COUNT, COUNT);
        for ( size_t i = 0; i < COUNT; ++i ) {
            _ASSERT(!arr->m_Array[i].IsInHeap());
        }
        sw.Start();
        delete arr;
        double t2 = sw.Elapsed();
        message("static CObjectWithTLS", "create", t1, "delete", t2, COUNT);
    }
    check_cnts();
    {
        sw.Start();
        s_CurrentStep = "CObjectWithRef[]";
        CArray<CObjectWithRef, COUNT, false>* arr =
            new CArray<CObjectWithRef, COUNT, false>;
        double t1 = sw.Elapsed();
        check_cnts(COUNT, COUNT);
        for ( size_t i = 0; i < COUNT; ++i ) {
            _ASSERT(!arr->m_Array[i].CanBeDeleted());
        }
        sw.Start();
        delete arr;
        double t2 = sw.Elapsed();
        message("static CObjectWithRef", "create", t1, "delete", t2, COUNT);
    }
    check_cnts();
}