#include <glwebtools/internal/glwebtools_default_config.h>
#include <glwebtools/internal/glwebtools_version.h>
#include <glwebtools/internal/glwebtools_glwebtoolscore.h>
#include <glwebtools/internal/glwebtools_macro.h>
#include <glwebtools/internal/glwebtools_handlemanager.h>
#include <glwebtools/os/glwebtools_thread.h>
#include <glwebtools/os/glwebtools_systemclock.h>
#include <glwebtools/glwebtools_error.h>
#include <list>
#include <sstream>
#include <limits>
//
//#define GLWEBTOOLS_URL_CONNECTION_HANDLE_TYPE 1
//#define GLWEBTOOLS_URL_REQUEST_HANDLE_TYPE 2
namespace glwebtools
{
unsigned int GlWebToolsCore::s_urlConnectionHandleTypeId = 0;
unsigned int GlWebToolsCore::s_urlRequestHandleTypeId = 0;
//error function
bool IsOperationSuccess(glwebtools::Error code)
{
// may want to add extra processing if defined GLWEBTOOLS_DEBUG
return code == glwebtools::E_SUCCESS;
}
extern bool GetAppInfo(glwebtools::String& appIdentifier, glwebtools::String& appVersion, glwebtools::String& osIdentifier, glwebtools::String& osVersion, glwebtools::String& deviceIdentifier);
GlWebTools::CreationSettings::CreationSettings()
:m_isThreadedUpdate(GLWEBTOOLS_WEBTOOLS_THREADED_UPDATE)
,m_threadedUpdatePeriod(GLWEBTOOLS_WEBTOOLS_THREADED_UPDATE_PERIOD)
,m_updateThreadPriority(GLWEBTOOLS_WEBTOOLS_THREADED_UPDATE_PRIORITY)
,m_connectionMinThreadCount(GLWEBTOOLS_DEFAULT_TASKGROUP_MIN_THREADS)
,m_connectionMaxThreadCount(GLWEBTOOLS_DEFAULT_TASKGROUP_MAX_THREADS)
,m_connectionThreadPriority(GLWEBTOOLS_DEFAULT_TASKGROUP_THREAD_PRIORITY)
,m_connectionHysteresis_ms(GLWEBTOOLS_DEFAULT_TASKGROUP_HYSTERESIS)
,m_maxThreadStartTime_ms(GLWEBTOOLS_DEFAULT_TASKGROUP_MAX_THREAD_STARTING_TIME)
{
GetAppInfo(m_applicationIdentifier, m_applicationVersion, m_osIdentifier, m_osVersion, m_deviceIdentifier);
}
glwebtools::Error GlWebToolsCore::CreateInstance(GlWebToolsCore*& glWebToolsCore)
{
GlWebToolsCore* temp = 0;
temp = GLWEBTOOLS_NEW GlWebToolsCore();
if (temp == 0)
{
return glwebtools::E_MEMORY_ERROR;
}
glWebToolsCore = temp;
return glwebtools::E_SUCCESS;
}
glwebtools::Error GlWebToolsCore::DestroyInstance(GlWebToolsCore* glWebToolsCore)
{
if(glWebToolsCore == 0)
return E_INVALID_PARAMETER;
if(glWebToolsCore->CanDelete() == false)
return E_INVALID_OPERATION;
GLWEBTOOLS_DELETE(glWebToolsCore);
return glwebtools::E_SUCCESS;
}
bool GlWebToolsCore::CanDelete() const
{
LockScope _ls(m_mutex);
return (m_refCount < 1) && (m_urlConnections.size() == 0) && (m_urlRequests.size() == 0);
}
bool GlWebToolsCore::HasRunningConnection()
{
LockScope _ls(m_mutex);
return _HasRunningConnection();
}
bool GlWebToolsCore::_HasRunningConnection()
{
UrlConnectionRefMap::iterator iterConnection = m_urlConnections.begin();
UrlConnectionRefMap::iterator endConnection = m_urlConnections.end();
for(;iterConnection != endConnection; ++iterConnection)
{
if(iterConnection->second->GetState() == glwebtools::UrlConnection::S_RUNNING)
return true;
}
return false;
}
unsigned int GlWebToolsCore::Grab()
{
LockScope _ls(m_mutex);
return Managed::Grab();
}
unsigned int GlWebToolsCore::Drop()
{
LockScope _ls(m_mutex);
return Managed::Drop();
}
bool GlWebToolsCore::IsInitialized() const
{
return m_isInitialized;
}
glwebtools::Error GlWebToolsCore::Initialize(const GlWebTools::CreationSettings& cs)
{
// LockScope _ls(m_mutex);
if(!m_isInitialized)
{
if (s_urlConnectionHandleTypeId == 0)
{
if(!HandleManager::RegisterType(s_urlConnectionHandleTypeId))
{
//could not register handle type
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_ASSERT(s_urlConnectionHandleTypeId);
GLWEBTOOLS_LOG_FATAL_ERROR("%s", "Failed to register handlable object to handle manager");
#endif
return glwebtools::E_TYPE_REGISTRATION_ERROR;
}
}
if (s_urlRequestHandleTypeId == 0)
{
if(!HandleManager::RegisterType(s_urlRequestHandleTypeId))
{
//could not register handle type
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_ASSERT(s_urlRequestHandleTypeId);
GLWEBTOOLS_LOG_FATAL_ERROR("%s", "Failed to register handlable object to handle manager");
#endif
return glwebtools::E_MEMORY_ERROR;
}
}
//set user agent
m_userAgent.clear();
if(cs.m_applicationIdentifier.size() > 0)
{
m_userAgent.append(cs.m_applicationIdentifier);
m_userAgent.append("/");
m_userAgent.append(cs.m_applicationVersion);
}
m_userAgent.append(" GlWebTools/");
m_userAgent.append(GLWEBTOOLS_VERSION);
m_userAgent.append(" ");
m_userAgent.append(cs.m_osIdentifier);
m_userAgent.append("/");
m_userAgent.append(cs.m_osVersion);
m_userAgent.append(" (");
m_userAgent.append(cs.m_deviceIdentifier);
m_userAgent.append(")");
#if GLWEBTOOLS_USE_OPENSSL
if (m_openSSL.IsInitialized() == false)
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_FATAL_ERROR("%s", "Failed to initialize OpenSSL");
#endif
return E_INITIALIZATION_ERROR;
}
#endif //GLWEBTOOLS_USE_OPENSSL
m_creationSettings = cs;
if(m_creationSettings.m_isThreadedUpdate)
{
m_thread = GLWEBTOOLS_NEW glwebtools::Thread(GlWebToolsCore::UpdateStatic, this, 0, "GlWebToolsThread");
if(m_thread)
{
m_isRunning = true;
m_thread->Start(m_creationSettings.m_updateThreadPriority);
}
else
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_ASSERT(m_thread);
GLWEBTOOLS_LOG_FATAL_ERROR("%s", "Failed to create thread for threaded update");
#endif
return E_INITIALIZATION_ERROR;
}
}
GLWEBTOOLS_RETURN_ERROR_ON_FAIL(AddDefaultTaskGroup());
TaskGroup::CreationSettings sseTaskGroupSettings;
sseTaskGroupSettings.m_minThreadCount = 0;
sseTaskGroupSettings.m_maxThreadCount = (unsigned int)(-1);
sseTaskGroupSettings.m_hysteresis_ms = 0;
sseTaskGroupSettings.m_maxThreadStartTime_ms = 1000;
m_sseTaskGroup.Initialize(sseTaskGroupSettings);
if(m_creationSettings.m_instanceName.empty())
{
std::stringstream ss;
ss << std::hex << reinterpret_cast<glwebtools::uptr_t>(this);
m_creationSettings.m_instanceName = ss.str();
}
m_isInitialized = true;
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_VERBOSE("GlWebTools %s is running", GLWEBTOOLS_VERSION_COMPLETE);
#endif
return glwebtools::E_SUCCESS;
}
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_ASSERT(!s_isInitialized);
GLWEBTOOLS_LOG_MINOR_ERROR("%s", "GlWebTools already initialized");
#endif
return glwebtools::E_INVALID_OPERATION;
}
glwebtools::Error GlWebToolsCore::_WaitForCanDelete(unsigned int milliseconds)
{
u64 accumulated_time = 0;
while (CanDelete()==false && accumulated_time < milliseconds)
{
const u64 start_time = SystemClock::GetMilliseconds();
glwebtools::Thread::Sleep(GLWEBTOOLS_URL_CONNECTION_SHUTDOWN_STEP_MS);
const u64 end_time = SystemClock::GetMilliseconds();
accumulated_time += (end_time - start_time);
if(!m_creationSettings.m_isThreadedUpdate)
Update();
}
return glwebtools::E_SUCCESS;
}
glwebtools::Error GlWebToolsCore::Terminate(unsigned int milliseconds)
{
if (IsInitialized() == false)
return glwebtools::E_SUCCESS;
GLWEBTOOLS_RETURN_ERROR_ON_FAIL(Shutdown());
GLWEBTOOLS_RETURN_ERROR_ON_FAIL(_WaitForCanDelete(milliseconds));
return Terminate();
}
glwebtools::Error GlWebToolsCore::Terminate()
{
LockScope _ls(m_mutex);
if (IsInitialized() == false)
return glwebtools::E_SUCCESS;
m_shutdownInProgress = false;
ClearTaskGroups();
if(m_thread)
{
m_isRunning = false;
m_thread->Join();
GLWEBTOOLS_DELETE(m_thread);
m_thread = 0;
}
//TODO force connection + request cleanup
HandleManager* handleManager = glwebtools::HandleManager::GetInstance();
//first update connection
UrlConnectionRefMap::iterator iterConnection = m_urlConnections.begin();
UrlConnectionRefMap::iterator endConnection = m_urlConnections.end();
for(;iterConnection != endConnection; ++iterConnection)
{
if(handleManager)
handleManager->UnregisterNode(iterConnection->second->GetToken());
//Can only delete connection that are not running - will leak others ...
if(iterConnection->second->CanDelete())
{
GLWEBTOOLS_DELETE(iterConnection->second);
}
}
m_urlConnections.clear();
//second update request
UrlRequestRefMap::iterator iterRequest = m_urlRequests.begin();
UrlRequestRefMap::iterator endRequest = m_urlRequests.end();
for(;iterRequest != endRequest; ++iterRequest)
{
if(handleManager)
handleManager->UnregisterNode(iterRequest->second->GetToken());
//Can only delete request that are not running - will leak others ...
if(iterRequest->second->CanDelete())
{
GLWEBTOOLS_DELETE(iterRequest->second);
}
}
m_urlRequests.clear();
m_isInitialized = false;
return glwebtools::E_SUCCESS;
}
glwebtools::Error GlWebToolsCore::Shutdown()
{
LockScope _ls(m_mutex);
if (IsInitialized() == false)
return glwebtools::E_SUCCESS;
if (ShutdownInProgress() == true)
return glwebtools::E_SUCCESS;
m_shutdownInProgress = true;
if(_HasRunningConnection())
{
return _CancelAllConnections(); //Send a cancel instruction to all request
}
return glwebtools::E_SUCCESS;
}
bool GlWebToolsCore::ShutdownInProgress() const
{
return m_shutdownInProgress;
}
UrlConnection GlWebToolsCore::CreateUrlConnection()
{
return CreateUrlConnection(UrlConnection::CreationSettings());
}
UrlConnection GlWebToolsCore::CreateUrlConnection(const UrlConnection::CreationSettings& creationSettings)
{
LockScope _ls(m_mutex);
HandleManager* handleManager = glwebtools::HandleManager::GetInstance();
if(IsInitialized() && handleManager && ShutdownInProgress() == false)
{
UrlConnection::CreationSettings cs = creationSettings;
if(cs.m_userAgent.empty())
{
cs.m_userAgent = m_userAgent;//set useragent if not set in the creation settings
}
TaskGroup* taskGroup = 0;
if (cs.m_supportServerSideEvent)
{
taskGroup = &m_sseTaskGroup;
}
else
{
taskGroup = GetTaskGroup(cs.m_taskGroupId);
if (taskGroup == 0)
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_MAJOR_ERROR("Task group with id %s doesn\'t exist", cs.m_taskGroupId.c_str());
#endif
return UrlConnection();
}
}
UrlConnectionCore* urlConnection = GLWEBTOOLS_NEW UrlConnectionCore(cs, *taskGroup);
if(urlConnection)
{
UrlConnection handle;
unsigned int counter = HandleManager::GetNextCounterValue();
unsigned int token = 0;
bool result = handleManager->RegisterNode(s_urlConnectionHandleTypeId, counter, static_cast<void*>(urlConnection), token);
if(result)
{
urlConnection->SetToken(token);
handle = UrlConnection(token); //implicit grab
urlConnection->SetIntanceName(m_creationSettings.m_instanceName);
m_urlConnections[reinterpret_cast<uptr_t>(urlConnection)] = urlConnection;
}
else
{
GLWEBTOOLS_DELETE(urlConnection);
}
return handle;
}
}
return UrlConnection();
}
UrlRequest GlWebToolsCore::CreateUrlRequest()
{
UrlRequest::CreationSettings cs;
return CreateUrlRequest(cs);
}
UrlRequest GlWebToolsCore::CreateUrlRequest(UrlRequest::CreationSettings& cs)
{
LockScope _ls(m_mutex);
HandleManager* handleManager = glwebtools::HandleManager::GetInstance();
if(IsInitialized() && handleManager && ShutdownInProgress() == false)
{
UrlRequestCore* urlRequest = GLWEBTOOLS_NEW UrlRequestCore(cs);
if(urlRequest)
{
UrlRequest handle;
unsigned int counter = HandleManager::GetNextCounterValue();
unsigned int token = 0;
bool result = handleManager->RegisterNode(s_urlRequestHandleTypeId, counter, static_cast<void*>(urlRequest), token);
if(result)
{
urlRequest->SetToken(token);
handle = UrlRequest(token); //implicit grab
m_urlRequests[reinterpret_cast<uptr_t>(urlRequest)] = urlRequest;
}
else
{
GLWEBTOOLS_DELETE(urlRequest);
}
return handle;
}
}
return UrlRequest();
}
u64 GlWebToolsCore::UpdateTime()
{
const u64 current_time = SystemClock::GetMilliseconds();
const u64 last_update_time = m_last_update_time;
m_last_update_time = current_time;
if (last_update_time)
{
if (current_time > last_update_time)
{
return (current_time - last_update_time);
}
else
{
// roll-over
return ((std::numeric_limits<u64>::max)() - last_update_time + current_time);
}
}
// first update
return 0;
}
glwebtools::Error GlWebToolsCore::Update()
{
const u64 delta_time = UpdateTime();
glwebtools::Error result = glwebtools::E_SUCCESS;
if(m_mutex.TryLock())
{
HandleManager* handleManager = glwebtools::HandleManager::GetInstance();
if(IsInitialized() && handleManager)
{
result = UpdateTaskGroups(delta_time);
if(GLWEBTOOLS_FAIL(result))
{
m_mutex.Unlock();
return result;
}
for(UrlConnectionRefMap::iterator iterConnection = m_urlConnections.begin(); iterConnection != m_urlConnections.end(); ++iterConnection)
{
iterConnection->second->Update(delta_time);
}
std::list<uptr_t, glwebtools::SAllocator<uptr_t> > deleteList;
//first update connection
UrlConnectionRefMap::iterator iterConnection = m_urlConnections.begin();
UrlConnectionRefMap::iterator endConnection = m_urlConnections.end();
for(;iterConnection != endConnection; ++iterConnection)
{
if(iterConnection->second->CanDelete())
deleteList.push_back(iterConnection->first);
}
while(deleteList.size() > 0)
{
uptr_t id = deleteList.front();
deleteList.pop_front();
iterConnection = m_urlConnections.find(id);
if(iterConnection->second)
handleManager->UnregisterNode(iterConnection->second->GetToken());
GLWEBTOOLS_DELETE(iterConnection->second);
m_urlConnections.erase(iterConnection);
}
//second update request
UrlRequestRefMap::iterator iterRequest = m_urlRequests.begin();
UrlRequestRefMap::iterator endRequest = m_urlRequests.end();
for(;iterRequest != endRequest; ++iterRequest)
{
if(iterRequest->second->CanDelete())
deleteList.push_back(iterRequest->first);
}
while(deleteList.size() > 0)
{
uptr_t id = deleteList.front();
deleteList.pop_front();
iterRequest = m_urlRequests.find(id);
if(iterRequest->second)
handleManager->UnregisterNode(iterRequest->second->GetToken());
GLWEBTOOLS_DELETE(iterRequest->second);
m_urlRequests.erase(iterRequest);
}
}
else if(!IsInitialized())
{
result = glwebtools::E_INVALID_OPERATION;
}
else if(!handleManager)
{
result = glwebtools::E_INVALID_DATA;
}
m_mutex.Unlock();
}
return result;
}
bool GlWebToolsCore::CancelAllConnections()
{
LockScope _ls(m_mutex);
return GLWEBTOOLS_SUCCESS(_CancelAllConnections());
}
glwebtools::Error GlWebToolsCore::_CancelAllConnections()
{
//first update connection
UrlConnectionRefMap::iterator iterConnection = m_urlConnections.begin();
UrlConnectionRefMap::iterator endConnection = m_urlConnections.end();
for(;iterConnection != endConnection; ++iterConnection)
{
iterConnection->second->CancelRequest();
}
return glwebtools::E_SUCCESS;
}
GlWebToolsCore::~GlWebToolsCore()
{
if(IsInitialized())
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_ASSERT(false);
GLWEBTOOLS_LOG_MAJOR_ERROR("%s", "Calling destructor on GlWebTools before deintialization");
#endif
}
Terminate(GLWEBTOOLS_URL_CONNECTION_SHUTDOWN_TIMEOUT_MS);
}
//private:
GlWebToolsCore::GlWebToolsCore()
:m_isInitialized(false)
,m_shutdownInProgress(false)
,m_isRunning(false)
,m_last_update_time(0)
{
m_thread = 0;
}
void GlWebToolsCore::UpdateStatic(void* caller, void* /*param*/)
{
GlWebToolsCore* glWebTools = static_cast<GlWebToolsCore*>(caller);
if(glWebTools)
{
while(glWebTools->m_isRunning)
{
glWebTools->Update();
glwebtools::Thread::Sleep(glWebTools->m_creationSettings.m_threadedUpdatePeriod); //update time is really short compared to period so no need to adjust sleep
}
}
}
const TaskGroup* GlWebToolsCore::GetTaskGroup(const TaskGroupId& id) const
{
TaskGroupMap::const_iterator it = m_taskGroupMap.find(id);
if (it == m_taskGroupMap.end())
return 0;
return it->second;
}
TaskGroup* GlWebToolsCore::GetTaskGroup(const TaskGroupId& id)
{
TaskGroupMap::iterator it = m_taskGroupMap.find(id);
if (it == m_taskGroupMap.end())
return 0;
return it->second;
}
glwebtools::Error GlWebToolsCore::AddDefaultTaskGroup()
{
TaskGroup::CreationSettings creationSettings;
creationSettings.m_minThreadCount = m_creationSettings.m_connectionMinThreadCount;
creationSettings.m_maxThreadCount = m_creationSettings.m_connectionMaxThreadCount;
creationSettings.m_threadPriority = m_creationSettings.m_connectionThreadPriority;
creationSettings.m_hysteresis_ms = m_creationSettings.m_connectionHysteresis_ms;
creationSettings.m_maxThreadStartTime_ms = m_creationSettings.m_maxThreadStartTime_ms;
return AddTaskGroup(GLWEBTOOLS_DEFAULT_TASKGROUP_ID, creationSettings);
}
glwebtools::Error GlWebToolsCore::AddTaskGroup(const TaskGroupId& id)
{
TaskGroup::CreationSettings creationSettings;
creationSettings.m_minThreadCount = GLWEBTOOLS_URL_CONNECTION_MIN_THREADS;
creationSettings.m_maxThreadCount = GLWEBTOOLS_URL_CONNECTION_MAX_THREADS;
creationSettings.m_threadPriority = GLWEBTOOLS_URL_CONNECTION_THREAD_PRIORITY;
creationSettings.m_hysteresis_ms = GLWEBTOOLS_URL_CONNECTION_HYSTERESIS;
creationSettings.m_maxThreadStartTime_ms = GLWEBTOOLS_URL_CONNECTION_MAX_THREAD_STARTING_TIME;
return AddTaskGroup(id, creationSettings);
}
glwebtools::Error GlWebToolsCore::AddTaskGroup(const TaskGroupId& id, const TaskGroup::CreationSettings& creationSettings)
{
TaskGroupMap::iterator it = m_taskGroupMap.find(id);
if (it != m_taskGroupMap.end())
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_MAJOR_ERROR("Task group with id \"%s\" already exists", id.c_str());
#endif
return E_INVALID_PARAMETER;
}
TaskGroup* taskGroup = GLWEBTOOLS_NEW TaskGroup();
if (taskGroup == 0)
return E_MEMORY_ERROR;
Error error = taskGroup->Initialize(creationSettings);
if (GLWEBTOOLS_FAIL(error))
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_MAJOR_ERROR("%", "Error when initializing task group");
#endif
GLWEBTOOLS_DELETE(taskGroup);
return error;
}
m_taskGroupMap[id] = taskGroup;
return E_SUCCESS;
}
glwebtools::Error GlWebToolsCore::UpdateTaskGroups(u64 delta_time_ms)
{
for (TaskGroupMap::const_iterator it = m_taskGroupMap.begin(); it != m_taskGroupMap.end(); ++it)
{
Error error = (*it).second->Update(delta_time_ms);
if (GLWEBTOOLS_FAIL(error))
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_MAJOR_ERROR("%", "Error when updating task group");
#endif
}
}
Error error = m_sseTaskGroup.Update(delta_time_ms);
if (GLWEBTOOLS_FAIL(error))
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_MAJOR_ERROR("%", "Error when updating SSE task group");
#endif
}
return E_SUCCESS;
}
void GlWebToolsCore::ClearTaskGroups()
{
for (TaskGroupMap::const_iterator it = m_taskGroupMap.begin(); it != m_taskGroupMap.end(); ++it)
{
GLWEBTOOLS_DELETE((*it).second);
}
m_taskGroupMap.clear();
m_sseTaskGroup.Terminate();
}
/* GlWebTools */
GlWebTools::GlWebTools()
:m_glWebTools(0)
{
}
GlWebTools::~GlWebTools()
{
Release();
}
GlWebTools::GlWebTools(const GlWebTools& rhs)
:m_glWebTools(rhs.m_glWebTools)
{
if(m_glWebTools)
{
m_glWebTools->Grab();
GLWEBTOOLS_ASSERT(m_glWebTools->IsInitialized());
}
}
GlWebTools& GlWebTools::operator=(const GlWebTools& rhs)
{
if(this == &rhs)
return *this;
Release();
if(rhs.m_glWebTools)
{
m_glWebTools = rhs.m_glWebTools;
m_glWebTools->Grab();
GLWEBTOOLS_ASSERT(m_glWebTools->IsInitialized());
}
return *this;
}
glwebtools::Error GlWebTools::Release(unsigned int milliseconds)
{
if(IsInitialized())
{
if (m_glWebTools->Drop() == 0)
{
m_glWebTools->Terminate(milliseconds);
glwebtools::GlWebToolsCore::DestroyInstance(m_glWebTools);
}
m_glWebTools = 0;
}
return glwebtools::E_SUCCESS;
}
glwebtools::Error GlWebTools::Release()
{
if(IsInitialized())
{
if (m_glWebTools->Drop() == 0)
{
m_glWebTools->Terminate(GLWEBTOOLS_URL_CONNECTION_SHUTDOWN_TIMEOUT_MS);
glwebtools::GlWebToolsCore::DestroyInstance(m_glWebTools);
}
m_glWebTools = 0;
}
return glwebtools::E_SUCCESS;
}
glwebtools::Error GlWebTools::Initialize(const GlWebTools::CreationSettings& cs)
{
if (IsInitialized())
return glwebtools::E_INVALID_OPERATION;
GLWEBTOOLS_RETURN_ERROR_ON_FAIL(glwebtools::GlWebToolsCore::CreateInstance(m_glWebTools));
m_glWebTools->Grab();
glwebtools::Error result = m_glWebTools->Initialize(cs);
if (GLWEBTOOLS_FAIL(result))
{
Release();
}
return result;
}
glwebtools::Error GlWebTools::Shutdown()
{
if(IsInitialized() == false)
return glwebtools::E_INVALID_HANDLE;
return m_glWebTools->Shutdown();
}
glwebtools::Error GlWebTools::Terminate(unsigned int milliseconds)
{
if(IsInitialized() == false)
return glwebtools::E_INVALID_HANDLE;
if (m_glWebTools->m_refCount > 1)
{
#ifdef GLWEBTOOLS_DEBUG
GLWEBTOOLS_LOG_FATAL_ERROR("%s", "Failed to terminate glwebtools. There are still references on it.");
#endif
return glwebtools::E_INVALID_OPERATION;
}
return Release(milliseconds);
}
glwebtools::Error GlWebTools::Terminate()
{
return Terminate(GLWEBTOOLS_URL_CONNECTION_SHUTDOWN_TIMEOUT_MS);
}
UrlConnection GlWebTools::CreateUrlConnection()
{
if(IsInitialized())
{
return m_glWebTools->CreateUrlConnection();
}
return UrlConnection();
}
UrlConnection GlWebTools::CreateUrlConnection(UrlConnection::CreationSettings& cs)
{
if(IsInitialized())
{
return m_glWebTools->CreateUrlConnection(cs);
}
return UrlConnection();
}
UrlRequest GlWebTools::CreateUrlRequest()
{
if(IsInitialized())
{
return m_glWebTools->CreateUrlRequest();
}
return UrlRequest();
}
UrlRequest GlWebTools::CreateUrlRequest(UrlRequest::CreationSettings& cs)
{
if(IsInitialized())
{
return m_glWebTools->CreateUrlRequest(cs);
}
return UrlRequest();
}
glwebtools::Error GlWebTools::Update()
{
if(IsInitialized())
{
return m_glWebTools->Update();
}
return glwebtools::E_INVALID_HANDLE;
}
bool GlWebTools::IsInitialized() const
{
return m_glWebTools && m_glWebTools->IsInitialized();
}
bool GlWebTools::ShutdownInProgress() const
{
return (IsInitialized() && m_glWebTools->ShutdownInProgress());
}
glwebtools::Error GlWebTools::AddTaskGroup(const TaskGroupId& id, const TaskGroup::CreationSettings& creationSettings)
{
if(IsInitialized())
{
return m_glWebTools->AddTaskGroup(id, creationSettings);
}
return glwebtools::E_INVALID_HANDLE;
}
glwebtools::Error GlWebTools::AddTaskGroup(const TaskGroupId& id)
{
if(IsInitialized())
{
return m_glWebTools->AddTaskGroup(id);
}
return glwebtools::E_INVALID_HANDLE;
}
} //namespace glwebtools