Exemplo n.º 1
0
void Logic::processResponses(void) {
    ResponsePtr response;
    CheckResponsePtr checkResponse;
    CancelResponsePtr cancelResponse;
    SimpleCheckResponsePtr simpleResponse;
    while ((response = m_socketClient.getResponse())) {
        checkResponse = std::dynamic_pointer_cast<CheckResponse>(response);
        if (checkResponse) {
            processCheckResponse(*checkResponse);
            continue;
        }

        cancelResponse = std::dynamic_pointer_cast<CancelResponse>(response);
        if (cancelResponse) {
            processCancelResponse(*cancelResponse);
            continue;
        }

        simpleResponse = std::dynamic_pointer_cast<SimpleCheckResponse>(response);
        if (simpleResponse) {
            processSimpleCheckResponse(*simpleResponse);
            continue;
        }

        LOGC("Critical error. Casting Response to known response failed.");
        throw UnexpectedErrorException("Unexpected response from cynara service");
    }
}
Exemplo n.º 2
0
int Logic::registerInCynara(void) {
    ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber();

    //Ask cynara service
    AgentRegisterResponsePtr registerResponsePtr;
    AgentRegisterRequest request(m_agentType, sequenceNumber);
    ResponsePtr response = m_socketClient.askCynaraServer(request);
    if (!response) {
        LOGW("Disconnected by cynara server.");
        return CYNARA_API_SERVICE_NOT_AVAILABLE;
    }

    registerResponsePtr = std::dynamic_pointer_cast<AgentRegisterResponse>(response);
    if (!registerResponsePtr) {
        LOGC("Casting response to AgentRegisterResponse failed.");
        return CYNARA_API_UNKNOWN_ERROR;
    }
    LOGD("registerResponse: answer code [%d]", static_cast<int>(registerResponsePtr->m_code));

    switch (registerResponsePtr->m_code) {
        case AgentRegisterResponse::DONE:
            return CYNARA_API_SUCCESS;
        case AgentRegisterResponse::REJECTED:
            LOGE("Registering agent of type <%s> has been rejected", m_agentType.c_str());
            return CYNARA_API_ACCESS_DENIED;
        default:
            LOGE("Registering agent of type <%s> has finished with unknown error",
                 m_agentType.c_str());
            return CYNARA_API_UNKNOWN_ERROR;
    }
}
Exemplo n.º 3
0
/*static*/ void CGeoLocation::callback_geolocation(void *arg, String const &/*query*/ )
{
    if ( !rho_geo_is_available() )
    {
        rho_http_sendresponse(arg, "Unavailable;Unavailable;Unavailable");
        return;
    }

    if (!rho_geo_known_position())
    {
        rho_http_sendresponse(arg, "Reading;Reading;Reading");
        return;
    }
    
    double latitude = rho_geo_latitude();
    double longitude = rho_geo_longitude();

    char location[256];
    sprintf(location,"%.4f\xc2\xb0 %s, %.4f\xc2\xb0 %s;%f;%f",
        fabs(latitude),latitude < 0 ? "South" : "North",
        fabs(longitude),longitude < 0 ? "West" : "East",
        latitude,longitude);

    LOGC(INFO,CRhodesApp::getLogCategory())+ "Location: " + location;
    rho_http_sendresponse(arg, location);
}
Exemplo n.º 4
0
VALUE getallPhonebookRecords(void* pb) {
#if defined (_WIN32_WCE)//&& !defined( OS_PLATFORM_MOTCE )
	if (RHO_IS_WMDEVICE && pb) {
		CNativeAddressBook* phonebook = (CNativeAddressBook*)pb;
        VALUE valGc = rho_ruby_disable_gc();
        CHoldRubyValue hash(rho_ruby_createHash());
		
		std::vector<CABRecord*> records;
		phonebook->getAllRecords(records);
		while(records.size() > 0) {
			CABRecord* record = records.back();
			const char* rid = record->getValue("id").c_str();
			if (rid) {
				LOGC(TRACE,"Phonebook") + "Adding record " + rid;
				addHashToHash(hash,rid,_getRecord(record));
			}
			delete record;
			records.pop_back();
		}

        rho_ruby_enable_gc(valGc);
		return hash;
	}	
#endif
	return rho_ruby_get_NIL();	
}
Exemplo n.º 5
0
Arquivo: gfx.cpp Projeto: amecky/DT
	void shutdown() {
		LOGC("assets") << "shutting down context";
		for (size_t i = 0; i < assetCtx->textures.size(); ++i) {
			SAFE_RELEASE(assetCtx->textures[i].texture);
		}
		delete assetCtx;
		assetCtx = 0;
	}
Exemplo n.º 6
0
void WorkQueue::save(Serializer& writer) {
	int nr = _queue.size();
	writer.write(nr);
	LOGC("WorkQueue") << "saving " << nr << " work items";
    for ( int i = 0; i < nr; ++i ) {
		WorkItem& b = _queue[i];		
		writer.write(&b,sizeof(WorkItem));
    }
}
Exemplo n.º 7
0
Logic::CheckMap::iterator Logic::checkResponseValid(const Response &response) {
    auto it = m_checks.find(response.sequenceNumber());
    if (it == m_checks.end()) {
        LOGC("Critical error. Unknown checkResponse received: sequenceNumber = [%" PRIu16 "]",
             response.sequenceNumber());
        throw UnexpectedErrorException("Unexpected response from cynara service");
    }
    return it;
}
Exemplo n.º 8
0
Arquivo: gfx.cpp Projeto: amecky/DT
	// -------------------------------------------------
	// load texture
	// -------------------------------------------------
	int loadTexture(const char* name) {
		LOGC("assets") << "load texture: " << name;
		int idx = findTexture(name);
		if (idx != -1) {
			LOGC("assets") << "found already existing texture - returning " << idx;
			return idx;
		}
		TextureAsset asset;
		char fileName[256];
		sprintf(fileName, "content\\%s.png", name);
		LOGC("assets") << "loading texture from file: " << fileName;
		HRESULT result = D3DX11CreateShaderResourceViewFromFile(ctx->device, fileName, NULL, NULL, &asset.texture, NULL);
		if (FAILED(result)) {
			return -1;
		}
		assetCtx->textures.push_back(asset);
		return assetCtx->textures.size() - 1;
	}
Exemplo n.º 9
0
void Logic::processCancelResponse(const CancelResponse &cancelResponse) {

    auto it = checkResponseValid(cancelResponse);
    if (!it->second.cancelled()) {
        LOGC("Critical error. CancelRequest not sent: sequenceNumber = [%" PRIu16 "]",
             cancelResponse.sequenceNumber());
        throw UnexpectedErrorException("Unexpected response from cynara service");
    }
    releaseRequest(it);
}
Exemplo n.º 10
0
INetResponse* CNetRequestWrapper::pullFile(const String& strUrl, const String& strFilePath, IRhoSession* oSession, Hashtable<String,String>* pHeaders)
{
    common::CRhoFile oFile;
    if ( !oFile.open(strFilePath.c_str(),common::CRhoFile::OpenForAppend) ) 
    {
        LOGC(ERROR, "Net") + "pullFile: cannot create file :" + strFilePath;
        return m_pReqImpl->createEmptyNetResponse();
    }

    return m_pReqImpl->pullFile( strUrl, oFile, oSession, pHeaders );
}
Exemplo n.º 11
0
void WorkQueue::load(Serializer& reader) {
	_queue.clear();
	int nr = 0;
	reader.read(&nr);
	LOGC("WorkQueue") << "loading " << nr << " work items";
    for ( int i = 0; i < nr; ++i ) {
		WorkItem b;
		reader.read(&b,sizeof(WorkItem));
		_queue.push_back(b);
    }
}
Exemplo n.º 12
0
int saveRecord(void* pb, void* record) {
#if defined (_WIN32_WCE)
	if (record) {
		CABRecord* r = (CABRecord*)record;
		LOGC(INFO,"Phonebook") + "About to save:";
		r->dump();
		r->save();
		delete  r;
	}
#endif
	return 1;
}
Exemplo n.º 13
0
int Logic::requestResult(const PolicyKey &key, PolicyResult &result) {
    auto checkResponse = requestResponse<CheckRequest, CheckResponse>(key);
    if (!checkResponse) {
        LOGC("Critical error. Requesting CheckResponse failed.");
        return CYNARA_API_SERVICE_NOT_AVAILABLE;
    }
    LOGD("checkResponse: policyType = %" PRIu16 ", metadata = %s",
         checkResponse->m_resultRef.policyType(),
         checkResponse->m_resultRef.metadata().c_str());
    result = checkResponse->m_resultRef;
    return CYNARA_API_SUCCESS;
}
Exemplo n.º 14
0
// ------------------------------------------------------
// remove work at location for specific price_type
// ------------------------------------------------------
void WorkQueue::remove(WorkType work_type, int x, int y) {
	LOGC("WorkQueue") << "removing " << _price_registry->translateWorkType(work_type) << " at " << x << " " << y;
	Queue::iterator it = _queue.begin();
	while (it != _queue.end()) {
		if ( it->tile_x == x && it->tile_y == y && it->price_index == work_type) {
			it = _queue.erase(it);
		}
		else {
			++it;
		}
	}
}
Exemplo n.º 15
0
int saveRecord(void* pb, void* record) {
#if defined (_WIN32_WCE)//&& !defined( OS_PLATFORM_MOTCE )
	if (RHO_IS_WMDEVICE && record) {
		CABRecord* r = (CABRecord*)record;
		LOGC(INFO,"Phonebook") + "About to save:";
		r->dump();
		r->save();
		delete  r;
	}
#endif
	return 1;
}
Exemplo n.º 16
0
int main(int argc, char **argv) {
    init_log();

    try {
        if (1 < argc) {
            auto handlingSuccess = Cynara::CmdlineParser::handleCmdlineOptions(argc, argv);
            return (handlingSuccess ? EXIT_SUCCESS : EXIT_FAILURE);
        }

        Cynara::Cynara cynara;
        LOGI("Cynara service is starting ...");
        cynara.init();
        LOGI("Cynara service is started");

        int ret = sd_notify(0, "READY=1");
        if (ret == 0) {
            LOGW("Cynara was not configured to notify its status");
        } else if (ret < 0) {
            LOGE("sd_notify failed [%d]", ret);
        }

        LOGD("Starting the real job");
        cynara.run();

        LOGD("Time to clean up.");
        cynara.finalize();
        LOGD("Cynara service is stopped");
    } catch (std::exception &e) {
        LOGC("Cynara stoped because of unhandled exception: %s", e.what());
        return EXIT_FAILURE;
    } catch (...) {
        LOGC("Cynara stoped because of unknown unhanndled exception.");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
Exemplo n.º 17
0
int Logic::requestSimpleResult(const PolicyKey &key, PolicyResult &result) {
    auto simpleCheckResponse = requestResponse<SimpleCheckRequest, SimpleCheckResponse>(key);
    if (!simpleCheckResponse) {
        LOGC("Critical error. Requesting SimpleCheckResponse failed.");
        return CYNARA_API_SERVICE_NOT_AVAILABLE;
    }

    if (simpleCheckResponse->getReturnValue() != CYNARA_API_SUCCESS)
        return simpleCheckResponse->getReturnValue();

    LOGD("SimpleCheckResponse: policyType = %" PRIu16 ", metadata = %s",
         simpleCheckResponse->getResult().policyType(),
         simpleCheckResponse->getResult().metadata().c_str());

    result = simpleCheckResponse->getResult();
    return CYNARA_API_SUCCESS;
}
Exemplo n.º 18
0
int main()
{


	// Makes sure ResourceManager initializes before everything else.
	ResourceManager& resourceManager = ResourceManager::getInstance();
	resourceManager.init();

	// Run the stateMachine
	StateMachine stateMachine;
	stateMachine.run();
	
	// Wait for the console window to be closed.
	std::cout << "\n\n";
	LOGC("You can close the program when you have read the log above :)\nBe patient for this window to close");
	while (true) {
		Sleep(100);
	}
    return EXIT_SUCCESS;
}
Exemplo n.º 19
0
// ------------------------------------------------------
// create work item
// ------------------------------------------------------
void WorkQueue::createWork(WorkType work_type,int x,int y, int building_id, int level,int duration) {
	LOGC("WorkQueue") << "create work " << _price_registry->translateWorkType(work_type) << " at " << x << " " << y << " for building " << building_id << "/" << level << " duration: " << duration;
	WorkItem item;
	item.tile_x = x;
	item.tile_y = y;
	if ( work_type == PT_REGULAR) {
		item.reschedule = true;
	}
	else {
		item.reschedule = false;
	}
	item.price_index = work_type;
	item.duration = duration;
	item.timer = 0;
	item.work_type = work_type;
	item.building_id = building_id;
	item.level = level;
	item.done = false;
	_queue.push_back(item);	
}
Exemplo n.º 20
0
bool
XWindowsClipboard::icccmGetSelection(Atom target,
				Atom* actualTarget, String* data) const
{
	assert(actualTarget != NULL);
	assert(data         != NULL);

	// request data conversion
	CICCCMGetClipboard getter(m_window, m_time, m_atomData);
	if (!getter.readClipboard(m_display, m_selection,
								target, actualTarget, data)) {
		LOG((CLOG_DEBUG1 "can't get data for selection target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
		LOGC(getter.m_error, (CLOG_WARN "ICCCM violation by clipboard owner"));
		return false;
	}
	else if (*actualTarget == None) {
		LOG((CLOG_DEBUG1 "selection conversion failed for target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
		return false;
	}
	return true;
}
Exemplo n.º 21
0
void InMemoryStorageBackend::load(void) {
    bool isBackupValid = m_integrity.backupGuardExists();
    std::string bucketSuffix = "";
    std::string indexFilename = m_dbPath + m_indexFilename;
    std::string chsFilename = m_dbPath + m_chsFilename;

    if (isBackupValid) {
        bucketSuffix += m_backupFilenameSuffix;
        indexFilename += m_backupFilenameSuffix;
        chsFilename += m_backupFilenameSuffix;
    }

    try {
        std::ifstream chsStream;
        openFileStream(chsStream, chsFilename, isBackupValid);
        m_checksum.load(chsStream);

        auto indexStream = std::make_shared<std::ifstream>();
        openFileStream(*indexStream, indexFilename, isBackupValid);

        StorageDeserializer storageDeserializer(indexStream,
            std::bind(&InMemoryStorageBackend::bucketStreamOpener, this,
                      std::placeholders::_1, bucketSuffix, isBackupValid));

        storageDeserializer.initBuckets(buckets());
        storageDeserializer.loadBuckets(buckets());
    } catch (const DatabaseException &) {
        LOGC("Reading cynara database failed.");
        buckets().clear();
        throw DatabaseCorruptedException();
    }
    m_checksum.clear();

    if (!hasBucket(defaultPolicyBucketId)) {
        LOGN("Creating defaultBucket.");
        this->buckets().insert({ defaultPolicyBucketId, PolicyBucket(defaultPolicyBucketId) });
    }

    postLoadCleanup(isBackupValid);
}
Exemplo n.º 22
0
bool SimForth::parseCell(ASpreadSheetCell &cell)
{
  bool res = true;
  std::string word;
  ASpreadSheetCell *c;

  LOGD("parseCell %s: %s", cell.name().c_str(),
       cell.formulae().c_str());

  //assert(nullptr != m_spreadsheet);
  if (nullptr == m_spreadsheet)
    {
      LOGD("No spreadsheet attached to a Forth interpreter");
      return false;
    }

  m_err_stream = 0;
  STREAM.loadString(cell.formulae(), cell.name());

  try
    {
      while (STREAM.hasMoreWords())
        {
          c = isACell(STREAM.nextWord());
          if (nullptr != c)
            {
              cell.addReference(*c);
            }
        }
    }
  catch (ForthException const& e)
    {
      LOGC("parseCell caught Forth Exception '%s'", e.message().c_str());
      cell.reset();
      res = false;
    }

  return res;
}
Exemplo n.º 23
0
int Logic::getRequest(AgentActionResponsePtr &resultPtr) {
    int ret = ensureConnection();
    if (ret != CYNARA_API_SUCCESS)
        return ret;

    ResponsePtr responsePtr = m_socketClient.getBufferedResponse();
    if (responsePtr == nullptr) {
        AgentSocketState state = m_socketClient.waitForEvent();
        switch (state) {
        case AgentSocketState::SS_QUITREQUEST:
            LOGD("Waiting interrupted. Finishing");
            m_notify.snooze();
            return CYNARA_API_INTERRUPTED;
        case AgentSocketState::SS_REQUEST:
        {
            responsePtr = m_socketClient.receiveResponseFromServer();
            if (!responsePtr) {
                LOGW("Disconnected by cynara server.");
                return CYNARA_API_SERVICE_NOT_AVAILABLE;
            }
            break;
        }
        default:
            LOGE("Wrong state returned [" << state << "]");
            return CYNARA_API_UNKNOWN_ERROR;
        }
    }
    AgentActionResponsePtr actionResponsePtr =
        std::dynamic_pointer_cast<AgentActionResponse>(responsePtr);
    if (!actionResponsePtr) {
        LOGC("Casting request to AgentActionResponse failed.");
        return CYNARA_API_UNKNOWN_ERROR;
    }
    LOGD("agentActionResponse: type: [%" PRIu8 "], data length: [%zu]",
         actionResponsePtr->type(), actionResponsePtr->data().size());

    resultPtr = actionResponsePtr;
    return CYNARA_API_SUCCESS;
}
Exemplo n.º 24
0
//==============================================================================
ChessGame::ChessGame(
    const GameConfigPtr &spConfig,
    const fly::SocketPtr &spClientSocket,
    const MoveSetPtr &spMoveSet,
    const color_type &engineColor,
    const value_type &difficulty
) :
    m_spConfig(spConfig),
    m_gameId(spClientSocket->GetSocketId()),
    m_wpClientSocket(spClientSocket),
    m_wpMoveSet(spMoveSet),
    m_maxDepth(2 * difficulty + 1),
    m_checkMaxDepth(m_spConfig->IncreaseEndGameDifficulty()),
    m_spBoard(std::make_shared<BitBoard>()),
    m_moveSelector(spMoveSet, m_spBoard, engineColor)
{
    LOGC("Initialized game %d: Engine color = %d, max depth = %d",
        m_gameId, engineColor, m_maxDepth);

    LOGI(m_gameId, "Initialized game: Engine color = %d, max depth = %d",
        engineColor, m_maxDepth);
}
Exemplo n.º 25
0
int Logic::getRequest(AgentActionResponsePtr &resultPtr) {
    int ret = ensureConnection();
    if (ret != CYNARA_API_SUCCESS)
        return ret;

    ResponsePtr responsePtr = m_socketClient.receiveResponseFromServer();
    if (!responsePtr) {
        LOGW("Disconnected by cynara server.");
        return CYNARA_API_SERVICE_NOT_AVAILABLE;
    }

    AgentActionResponsePtr actionResponsePtr =
        std::dynamic_pointer_cast<AgentActionResponse>(responsePtr);
    if (!actionResponsePtr) {
        LOGC("Casting request to AgentActionResponse failed.");
        return CYNARA_API_UNKNOWN_ERROR;
    }
    LOGD("agentActionResponse: type: [%" PRIu8 "], data length: [%zu]",
         actionResponsePtr->type(), actionResponsePtr->data().size());

    resultPtr = actionResponsePtr;
    return CYNARA_API_SUCCESS;
}
Exemplo n.º 26
0
VALUE getallPhonebookRecords(void* pb) {
#if defined (_WIN32_WCE)
	if (pb) {
		CNativeAddressBook* phonebook = (CNativeAddressBook*)pb;
		VALUE hash = createHash();
		
		std::vector<CABRecord*> records;
		phonebook->getAllRecords(records);
		while(records.size() > 0) {
			CABRecord* record = records.back();
			const char* rid = record->getValue("id").c_str();
			if (rid) {
				LOGC(TRACE,"Phonebook") + "Adding record " + rid;
				addHashToHash(hash,rid,_getRecord(record));
			}
			delete record;
			records.pop_back();
		}

		return hash;
	}
#endif
	return rho_ruby_get_NIL();	
}
AiShipBehaviorAttackCapitalShip::AiShipBehaviorAttackCapitalShip(AiShipController & aiShipController)
		: AiShipBehaviorAttack(aiShipController)
{
	LOGC(ConfigServerGame::isSpaceAiLoggingEnabled(), "space_debug_ai", ("AiShipBehaviorAttackCapitalShip::AiShipBehaviorAttackCapitalShip() unit(%s)", (m_aiShipController.getOwner() != NULL) ? m_aiShipController.getOwner()->getNetworkId().getValueString().c_str() : "NULL owner"));
}
AiShipBehaviorTrack::AiShipBehaviorTrack(AiShipController & aiShipController, Object const & target)
 : AiShipBehaviorBase(aiShipController)
 , m_target(&target)
{
	LOGC(ConfigServerGame::isSpaceAiLoggingEnabled(), "space_debug_ai", ("AiShipBehaviorTrack() unit(%s) target(%s)", (m_aiShipController.getOwner() != NULL) ? m_aiShipController.getOwner()->getNetworkId().getValueString().c_str() : "NULL owner", target.getNetworkId().getValueString().c_str()));
}
Exemplo n.º 29
0
rho::net::CNetResponseWrapper CNetRequestWrapper::pullFile(const String& strUrl, const String& strFilePath, IRhoSession* oSession, Hashtable<String,String>* pHeaders,bool overwriteFile,bool createFolders, bool* pFileExistsFlag )
{
    if (!overwriteFile && common::CRhoFile::isFileExist(strFilePath.c_str())) {
        LOGC(WARNING,"Net") + "pullFile: " + strFilePath + " already exists, won't download since overwrite flag is not set";
        
        if ( pFileExistsFlag != 0 ) {
            *pFileExistsFlag = true;
        }
        
        return m_pReqImpl->createEmptyNetResponse();
    }
    
    if ( pFileExistsFlag != 0 ) {
        *pFileExistsFlag = false;
    }
    
    if ( createFolders ) {
        String targetDir = common::CFilePath(strFilePath).getFolderName();
        
        if ( !common::CRhoFile::isDirectory(targetDir.c_str()) ) {
            common::CRhoFile::recursiveCreateDir(targetDir.c_str(), "");
        }
    }
    
    String tmpfilename = strFilePath + ".rhodownload";
    String modfilename = strFilePath + ".modtime";
    
    common::CRhoFile tmpFile;
    common::CRhoFile::EOpenModes openMode = common::CRhoFile::OpenForWrite;
    
    //don't request headers of will overwrite anyway
    if (!overwriteFile) {
        Hashtable<String, String> h;
        ::getNetRequest().doRequest("HEAD", strUrl, "", oSession, &h );
    
        if ( h.containsKey("last-modified") )
        {
            if ( common::CRhoFile::isFileExist(modfilename.c_str()) ) {
                String modDate;
                common::CRhoFile fModDate;
                if ( fModDate.open(modfilename.c_str(), common::CRhoFile::OpenReadOnly)) {
                    fModDate.readString(modDate);
                    if (modDate == h.get("last-modified")) {
                        openMode = common::CRhoFile::OpenForAppend;
                    }
                }
            } else {
                common::CRhoFile fModDate;
                if ( fModDate.open(modfilename.c_str(), common::CRhoFile::OpenForWrite) ) {
                    const String& modDate = h.get("last-modified");
                    fModDate.write((void*)modDate.c_str(), modDate.length());
                }
            }
        }
    }
    
    if ( !tmpFile.open(tmpfilename.c_str(),openMode) )
    {
        LOGC(ERROR, "Net") + "pullFile: cannot create file :" + tmpfilename;
        return m_pReqImpl->createEmptyNetResponse();
    }
    
    INetResponse* pResp = m_pReqImpl->pullFile( strUrl, tmpFile, oSession, pHeaders );
    
    tmpFile.close();
    
    if ( (pResp->getRespCode() == 200) || (pResp->getRespCode() == 206) ) 
    {
        common::CRhoFile::deleteFile(strFilePath.c_str());

        if ( common::CRhoFile::renameFile( tmpfilename.c_str(), strFilePath.c_str() ) != 0 ) 
        {
            LOGC(ERROR, "Net") + "pullFile: cannot rename file :" + tmpfilename + " to " + strFilePath;
            return m_pReqImpl->createEmptyNetResponse();
        }
        
        common::CRhoFile::deleteFile(modfilename.c_str());
    }
    
    return pResp;
}
    virtual bool run(JobQueue& job_queue)
    {
        size_t n = strptr.size();

        LOGC(debug_jobs)
            << "Process SmallsortJob8 " << this << " of size " << n;

        strptr = strptr.copy_back();

        if (n < g_inssort_threshold) {
            inssort::inssort_generic(strptr.copy_back().active(), depth);
            return true;
        }

        Char* charcache = new Char[n];

        // std::deque is much slower than std::vector, so we use an artificial
        // pop_front variable.
        size_t pop_front = 0;
        std::vector<RadixStep8_CI> radixstack;
        radixstack.emplace_back(strptr, depth, charcache);

        while (radixstack.size() > pop_front)
        {
            while (radixstack.back().idx < 255)
            {
                RadixStep8_CI& rs = radixstack.back();
                size_t b = ++rs.idx; // process the bucket rs.idx

                size_t bktsize = rs.bkt[b + 1] - rs.bkt[b];

                if (bktsize == 0)
                    continue;
                else if (bktsize < g_inssort_threshold)
                {
                    inssort::inssort_generic(
                        rs.strptr.sub(rs.bkt[b], bktsize).copy_back().active(),
                        depth + radixstack.size());
                }
                else
                {
                    radixstack.emplace_back(rs.strptr.sub(rs.bkt[b], bktsize),
                                            depth + radixstack.size(),
                                            charcache);
                }

                if (use_work_sharing && job_queue.has_idle())
                {
                    // convert top level of stack into independent jobs
                    LOGC(debug_jobs)
                        << "Freeing top level of SmallsortJob8's radixsort stack";

                    RadixStep8_CI& rt = radixstack[pop_front];

                    while (rt.idx < 255)
                    {
                        b = ++rt.idx; // enqueue the bucket rt.idx

                        size_t bktsize = rt.bkt[b + 1] - rt.bkt[b];

                        if (bktsize == 0) continue;
                        EnqueueSmallsortJob8(
                            job_queue, rt.strptr.sub(rt.bkt[b], bktsize),
                            depth + pop_front);
                    }

                    // shorten the current stack
                    ++pop_front;
                }
            }
            radixstack.pop_back();
        }

        delete[] charcache;

        return true;
    }