doc_and_tools/tools/sdk/include/ref/ref.h

209 lines
6.3 KiB
C++

// ref.h : the base utility for life-cycle control by reference
//
// Author: Gongbing
//
// Create: 2017-05-20
#pragma once
#ifdef _AS_DLL_
#ifdef _NET_EXPORTS_
#define PORT_API(ret) __declspec(dllexport) ret __stdcall
#define PORT_API_CALL(ret, call_) __declspec(dllexport) ret call_
#else
#define PORT_API(ret) __declspec(dllimport) ret __stdcall
#define PORT_API_CALL(ret, call_) __declspec(dllimport) ret call_
#ifdef _DEBUG
#pragma comment(lib, "./Debug/base_util.lib")
#else
#pragma comment(lib, "./Release/base_util.lib")
#endif
#endif
#else
#define PORT_API(ret) ret __stdcall
#define PORT_API_CALL(ret, call_) ret call_
#ifndef _BASE_EXPORTS_
#ifdef _DEBUG
#pragma comment(lib, "./Debug/base_util.lib")
#else
#pragma comment(lib, "./Release/base_util.lib")
#endif
#endif
#endif
//#define STRUCT_ALIGN(bytes) \
// #pragma pack(push) \
// #pragma pack(bytes)
//#define STRUCT_ALIGN_END \
// #pragma pack(pop)
#define COM_API_DECLARE(ret, decl) virtual ret __stdcall decl = 0
#define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret __stdcall decl
#define COM_API_OVERRIDE(ret, decl) virtual ret __stdcall decl override
#define COM_API_IMPLEMENT(cls, ret, decl) ret __stdcall cls##::decl
#define ALIGN_MEMORY(n, align) ((n + align - 1) / (align) * (align))
#define _TO_UNICODE_(str) L##str
#define UNICODE_STR(str) _TO_UNICODE_(str)
// refferer simulating-COM
namespace ref_util
{
//
// rule:
//
// if a member of container owns the container pointer, the member should release the container pointer
// in an explicit function like 'stop'; the container could release the member pointer in destructor!!!
//
__declspec(novtable) struct IRef
{
COM_API_DECLARE(long, add_ref(void));
COM_API_DECLARE(long, release(void));
};
class refer : public IRef
{
volatile long m_ref;
public:
refer() : m_ref(1)
{}
protected:
virtual ~refer()
{}
public:
COM_API_OVERRIDE(long, add_ref(void))
{
return InterlockedIncrement(&m_ref);
}
COM_API_OVERRIDE(long, release(void))
{
long ref = InterlockedDecrement(&m_ref);
if (ref <= 0) delete this;
return ref;
}
};
template<class T>
class auto_pointer
{
T* m_ptr;
public:
auto_pointer() : m_ptr(NULL)
{}
auto_pointer(T* ptr) : m_ptr(ptr)
{}
auto_pointer(const auto_pointer& r)
{
m_ptr = r.m_ptr;
if (m_ptr) m_ptr->add_ref();
}
~auto_pointer()
{
if (m_ptr) m_ptr->release();
}
public:
auto_pointer& operator=(T* ptr)
{
if (m_ptr) m_ptr->release();
m_ptr = ptr;
return *this;
}
auto_pointer& operator=(const auto_pointer& r)
{
if (m_ptr) m_ptr->release();
m_ptr = r.m_ptr;
if (m_ptr) m_ptr->add_ref();
return *this;
}
T* ptr(void)
{
return m_ptr;
}
T* operator->(void)
{
return m_ptr;
}
bool is_empty(void)
{
return m_ptr == NULL;
}
};
}
#define IMPL_REF_BY_REFER() \
COM_API_OVERRIDE(long, add_ref(void)) \
{ \
return ref_util::refer::add_ref(); \
} \
COM_API_OVERRIDE(long, release(void)) \
{ \
return ref_util::refer::release(); \
}
// inter-module data
namespace inter_module_data
{
enum data_flag
{
// commonly
DATA_FLAG_UNKNOWN = 0,
DATA_FLAG_ERROR, // the parameter 'len' is contains the error code, total is extension info for 'len'
DATA_FLAG_FINAL, // data is final result for the api which you called
DATA_FLAG_INSTAR, // data is instar for your api, and finally will notified with flag DATA_TYPE_FINAL
DATA_FLAG_OVER, // all data has been transfered, parameter data, len and total are all invalid
DATA_FLAG_GET_VAL, // (const wchar_t*)data, 'len' is bytes of data, 'total' is set_data
// call (set_data)total(const wchar_t* data, bytes of 'data', 0, DATA_FLAG_FINAL, param)
DATA_FLAG_DEBUG_INFO,
// for http data
DATA_FLAG_HTTP_HEAD = 100, // http(s) response head
DATA_FLAG_302, // 301 or 302 to new url, the data contains the url. in this case, return SET_RESULT_CONTINUE to jump, SET_RESULT_DISCARD to stop jumping
// for remote thread
DATA_FLAG_REMOTE_THREAD_INSTRUCT = 200, // to fill the remote thread code in given address
DATA_FLAG_REMOTE_THREAD_PARAMETER, // to fill the remote thread parameter in given address
// the parameter data, len and total will be all set to ZERO if unused
DATA_FALG_SVC_ENTER = 300, // service callback, called when initailizing, parameter 'data' is pointing to proc_util::ICmd*
DATA_FALG_SVC_TIMER, // service callback, called when timer is set, parameter 'len' is the count base from ZERO
DATA_FALG_SVC_CONTROL, // service callback, called when service control is invoked, parameter 'len' is the control code
DATA_FALG_SVC_EXIT, // service callback, called when service exiting
// for un-assembly
DATA_FLAG_UNASM_SET_LABEL = 1000, // set the label address, data is label, len is address, other has no mean
DATA_FLAG_UNASM_GET_LABEL, // query the label address. data is label, param is a pointer points to the UINT64 variable to receive the address
};
// return true to continue, false to stop
enum set_result
{
SET_RESULT_CONTINUE = ERROR_SUCCESS, // continue doing the task of the calling api
SET_RESULT_UNKNOWN = -100, // omit this value
SET_RESULT_DISCARD, // discard this data handling. i.e. it will stop jump to new url if flag is DATA_FLAG_302
SET_RESULT_STOP, // this will stop all operations of the api you calling
};
// real usage of these parameters, see the API which use this callback ...
typedef set_result(__stdcall* set_data)(const char* data // data buffer
, UINT64 len // bytes of data in data-buffer or error code if flag was DATA_FLAG_ERROR
, UINT64 total // total bytes of the data for the api which you called
, data_flag flag // data flag
, void* param); // user defined data, and passing it when call the callback
}
#define INTER_MODULE_CALLBACK(name) \
inter_module_data::set_result __stdcall name(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param)
#define INTER_MODULE_CALLBACK_VAR(name) \
inter_module_data::set_result (__stdcall *name)(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param)