Skip to content

Commit

Permalink
valgrind: use function-local initialization to implement singleton (X…
Browse files Browse the repository at this point in the history
  • Loading branch information
Wu Tao authored and HuangWei committed Nov 5, 2018
1 parent 91f32c0 commit 78c8ffd
Show file tree
Hide file tree
Showing 18 changed files with 64 additions and 106 deletions.
60 changes: 9 additions & 51 deletions include/dsn/utility/singleton.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,69 +24,27 @@
* THE SOFTWARE.
*/

/*
* Description:
* What is this file about?
*
* Revision history:
* xxxx-xx-xx, author, first version
* xxxx-xx-xx, author, fix bug about xxx
*/

#pragma once

#include <mutex>
#include <atomic>

namespace dsn {
namespace utils {

template <typename T>
class singleton
{
public:
singleton() {}
singleton() = default;

// disallow copy and assign
singleton(const singleton &) = delete;
singleton &operator=(const singleton &) = delete;

static T &instance()
{
if (nullptr == _instance) {
// lock
while (0 != _l.exchange(1, std::memory_order_acquire)) {
while (_l.load(std::memory_order_consume) == 1) {
}
}

// re-check and assign
if (nullptr == _instance) {
auto tmp = new T();
std::atomic_thread_fence(std::memory_order::memory_order_seq_cst);
_instance = tmp;
}

// unlock
_l.store(0, std::memory_order_release);
}
return *_instance;
static T _instance;
return _instance;
}

static T &fast_instance() { return *_instance; }

static bool is_instance_created() { return nullptr != _instance; }

protected:
static T *_instance;
static std::atomic<int> _l;

private:
singleton(const singleton &);
singleton &operator=(const singleton &);
};

// ----- inline implementations -------------------------------------------------------------------

template <typename T>
T *singleton<T>::_instance = 0;
template <typename T>
std::atomic<int> singleton<T>::_l(0);
}
} // end namespace dsn::utils
} // namespace utils
} // namespace dsn
4 changes: 2 additions & 2 deletions src/core/core/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ DSN_API dsn_log_level_t dsn_log_start_level = dsn_log_level_t::LOG_LEVEL_INFORMA

static void log_on_sys_exit(::dsn::sys_exit_type)
{
::dsn::logging_provider *logger = ::dsn::service_engine::fast_instance().logging();
::dsn::logging_provider *logger = ::dsn::service_engine::instance().logging();
if (logger != nullptr) {
logger->flush();
}
Expand Down Expand Up @@ -76,7 +76,7 @@ void dsn_log_init()
"flush-log - flush log to stderr or log file",
"flush-log",
[](const std::vector<std::string> &args) {
::dsn::logging_provider *logger = ::dsn::service_engine::fast_instance().logging();
::dsn::logging_provider *logger = ::dsn::service_engine::instance().logging();
if (logger != nullptr) {
logger->flush();
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/core/rpc_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ network *rpc_engine::create_network(const network_server_config &netcs,
bool client_only,
network_header_format client_hdr_format)
{
const service_spec &spec = service_engine::fast_instance().spec();
const service_spec &spec = service_engine::instance().spec();
network *net = utils::factory_store<network>::create(
netcs.factory_name.c_str(), ::dsn::PROVIDER_TYPE_MAIN, this, nullptr);
net->reset_parser_attr(client_hdr_format, netcs.message_buffer_block_size);
Expand Down
24 changes: 12 additions & 12 deletions src/core/core/service_api_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ DSN_API dsn_handle_t dsn_exlock_create(bool recursive)
{
if (recursive) {
::dsn::lock_provider *last = ::dsn::utils::factory_store<::dsn::lock_provider>::create(
::dsn::service_engine::fast_instance().spec().lock_factory_name.c_str(),
::dsn::service_engine::instance().spec().lock_factory_name.c_str(),
::dsn::PROVIDER_TYPE_MAIN,
nullptr);

// TODO: perf opt by saving the func ptrs somewhere
for (auto &s : ::dsn::service_engine::fast_instance().spec().lock_aspects) {
for (auto &s : ::dsn::service_engine::instance().spec().lock_aspects) {
last = ::dsn::utils::factory_store<::dsn::lock_provider>::create(
s.c_str(), ::dsn::PROVIDER_TYPE_ASPECT, last);
}
Expand All @@ -95,12 +95,12 @@ DSN_API dsn_handle_t dsn_exlock_create(bool recursive)
} else {
::dsn::lock_nr_provider *last =
::dsn::utils::factory_store<::dsn::lock_nr_provider>::create(
::dsn::service_engine::fast_instance().spec().lock_nr_factory_name.c_str(),
::dsn::service_engine::instance().spec().lock_nr_factory_name.c_str(),
::dsn::PROVIDER_TYPE_MAIN,
nullptr);

// TODO: perf opt by saving the func ptrs somewhere
for (auto &s : ::dsn::service_engine::fast_instance().spec().lock_nr_aspects) {
for (auto &s : ::dsn::service_engine::instance().spec().lock_nr_aspects) {
last = ::dsn::utils::factory_store<::dsn::lock_nr_provider>::create(
s.c_str(), ::dsn::PROVIDER_TYPE_ASPECT, last);
}
Expand Down Expand Up @@ -137,12 +137,12 @@ DSN_API dsn_handle_t dsn_rwlock_nr_create()
{
::dsn::rwlock_nr_provider *last =
::dsn::utils::factory_store<::dsn::rwlock_nr_provider>::create(
::dsn::service_engine::fast_instance().spec().rwlock_nr_factory_name.c_str(),
::dsn::service_engine::instance().spec().rwlock_nr_factory_name.c_str(),
::dsn::PROVIDER_TYPE_MAIN,
nullptr);

// TODO: perf opt by saving the func ptrs somewhere
for (auto &s : ::dsn::service_engine::fast_instance().spec().rwlock_nr_aspects) {
for (auto &s : ::dsn::service_engine::instance().spec().rwlock_nr_aspects) {
last = ::dsn::utils::factory_store<::dsn::rwlock_nr_provider>::create(
s.c_str(), ::dsn::PROVIDER_TYPE_ASPECT, last);
}
Expand Down Expand Up @@ -195,13 +195,13 @@ DSN_API dsn_handle_t dsn_semaphore_create(int initial_count)
{
::dsn::semaphore_provider *last =
::dsn::utils::factory_store<::dsn::semaphore_provider>::create(
::dsn::service_engine::fast_instance().spec().semaphore_factory_name.c_str(),
::dsn::service_engine::instance().spec().semaphore_factory_name.c_str(),
::dsn::PROVIDER_TYPE_MAIN,
initial_count,
nullptr);

// TODO: perf opt by saving the func ptrs somewhere
for (auto &s : ::dsn::service_engine::fast_instance().spec().semaphore_aspects) {
for (auto &s : ::dsn::service_engine::instance().spec().semaphore_aspects) {
last = ::dsn::utils::factory_store<::dsn::semaphore_provider>::create(
s.c_str(), ::dsn::PROVIDER_TYPE_ASPECT, initial_count, last);
}
Expand Down Expand Up @@ -606,7 +606,7 @@ bool run(const char *config_file,
::dsn::tls_trans_mem_init(tls_trans_memory_KB * 1024);

// prepare minimum necessary
::dsn::service_engine::fast_instance().init_before_toollets(spec);
::dsn::service_engine::instance().init_before_toollets(spec);

// init logging
dsn_log_init();
Expand All @@ -630,7 +630,7 @@ bool run(const char *config_file,
// TODO: register sys_exit execution

// init runtime
::dsn::service_engine::fast_instance().init_after_toollets();
::dsn::service_engine::instance().init_after_toollets();

dsn_all.engine_ready = true;

Expand Down Expand Up @@ -663,11 +663,11 @@ bool run(const char *config_file,
}
if (create_it) {
::dsn::service_engine::fast_instance().start_node(sp);
::dsn::service_engine::instance().start_node(sp);
}
}
if (::dsn::service_engine::fast_instance().get_all_nodes().size() == 0) {
if (::dsn::service_engine::instance().get_all_nodes().size() == 0) {
printf("no app are created, usually because \n"
"app_name is not specified correctly, should be 'xxx' in [apps.xxx]\n"
"or app_index (1-based) is greater than specified count in config file\n");
Expand Down
16 changes: 8 additions & 8 deletions src/core/core/service_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ bool service_node::rpc_unregister_handler(dsn::task_code rpc_code)

error_code service_node::init_io_engine()
{
auto &spec = service_engine::fast_instance().spec();
auto &spec = service_engine::instance().spec();
error_code err = ERR_OK;

// init disk engine
Expand All @@ -92,7 +92,7 @@ error_code service_node::init_io_engine()

error_code service_node::start_io_engine_in_main()
{
auto &spec = service_engine::fast_instance().spec();
auto &spec = service_engine::instance().spec();
error_code err = ERR_OK;

// start disk engine
Expand Down Expand Up @@ -294,16 +294,16 @@ std::string service_engine::get_runtime_info(const std::vector<std::string> &arg
{
std::stringstream ss;
if (args.size() == 0) {
ss << "" << service_engine::fast_instance()._nodes_by_app_id.size()
ss << "" << service_engine::instance()._nodes_by_app_id.size()
<< " nodes available:" << std::endl;
for (auto &kv : service_engine::fast_instance()._nodes_by_app_id) {
for (auto &kv : service_engine::instance()._nodes_by_app_id) {
ss << "\t" << kv.second->id() << "." << kv.second->full_name() << std::endl;
}
} else {
std::string indent = "";
int id = atoi(args[0].c_str());
auto it = service_engine::fast_instance()._nodes_by_app_id.find(id);
if (it != service_engine::fast_instance()._nodes_by_app_id.end()) {
auto it = service_engine::instance()._nodes_by_app_id.find(id);
if (it != service_engine::instance()._nodes_by_app_id.end()) {
auto args2 = args;
args2.erase(args2.begin());
it->second->get_runtime_info(indent, args2, ss);
Expand All @@ -318,8 +318,8 @@ std::string service_engine::get_queue_info(const std::vector<std::string> &args)
{
std::stringstream ss;
ss << "[";
for (auto &it : service_engine::fast_instance()._nodes_by_app_id) {
if (it.first != service_engine::fast_instance()._nodes_by_app_id.begin()->first)
for (auto &it : service_engine::instance()._nodes_by_app_id) {
if (it.first != service_engine::instance()._nodes_by_app_id.begin()->first)
ss << ",";
it.second->get_queue_info(ss);
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/core/task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ __thread uint16_t tls_dsn_lower32_task_id_mask = 0;
tls_dsn.current_task = nullptr;
tls_dsn.rpc = node->rpc();
tls_dsn.disk = node->disk();
tls_dsn.env = service_engine::fast_instance().env();
tls_dsn.env = service_engine::instance().env();
}

tls_dsn.node_pool_thread_ids = (node ? ((uint64_t)(uint8_t)node->id()) : 0)
Expand Down
6 changes: 3 additions & 3 deletions src/core/core/task_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ void task_worker_pool::create()

for (int i = 0; i < qCount; ++i) {
auto tsvc = factory_store<timer_service>::create(
service_engine::fast_instance().spec().timer_factory_name.c_str(),
service_engine::instance().spec().timer_factory_name.c_str(),
PROVIDER_TYPE_MAIN,
_node,
nullptr);
for (auto &s : service_engine::fast_instance().spec().timer_aspects) {
for (auto &s : service_engine::instance().spec().timer_aspects) {
tsvc =
factory_store<timer_service>::create(s.c_str(), PROVIDER_TYPE_ASPECT, _node, tsvc);
}
Expand Down Expand Up @@ -230,7 +230,7 @@ void task_engine::create(const std::list<threadpool_code> &pools)
// init pools
_pools.resize(threadpool_code::max() + 1, nullptr);
for (auto &p : pools) {
auto &s = service_engine::fast_instance().spec().threadpool_specs[p];
auto &s = service_engine::instance().spec().threadpool_specs[p];
auto workerPool = new task_worker_pool(s, this);
workerPool->create();
_pools[p] = workerPool;
Expand Down
8 changes: 4 additions & 4 deletions src/core/core/tool_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ tool_app::tool_app(const char *name) : tool_base(name) {}

void tool_app::start_all_apps()
{
auto apps = service_engine::fast_instance().get_all_nodes();
auto apps = service_engine::instance().get_all_nodes();
for (auto &kv : apps) {
task *t = new service_control_task(kv.second, true);
t->set_delay(1000 * kv.second->spec().delay_seconds);
Expand All @@ -90,16 +90,16 @@ void tool_app::start_all_apps()

void tool_app::stop_all_apps(bool cleanup)
{
auto apps = service_engine::fast_instance().get_all_nodes();
auto apps = service_engine::instance().get_all_nodes();
for (auto &kv : apps) {
task *t = new service_control_task(kv.second, false, cleanup);
t->enqueue();
}
}

const service_spec &tool_app::get_service_spec() { return service_engine::fast_instance().spec(); }
const service_spec &tool_app::get_service_spec() { return service_engine::instance().spec(); }

const service_spec &spec() { return service_engine::fast_instance().spec(); }
const service_spec &spec() { return service_engine::instance().spec(); }

const char *get_service_node_name(service_node *node) { return node->full_name(); }

Expand Down
1 change: 1 addition & 0 deletions src/core/core/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <fstream>
#include <memory>
#include <array>
#include <chrono>

#if defined(__linux__)
#include <sys/syscall.h>
Expand Down
6 changes: 3 additions & 3 deletions src/core/tests/netprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void rpc_client_session_send(rpc_session_ptr client_session)

TEST(tools_common, asio_net_provider)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;

Expand Down Expand Up @@ -160,7 +160,7 @@ TEST(tools_common, asio_net_provider)

TEST(tools_common, asio_udp_provider)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;

Expand Down Expand Up @@ -202,7 +202,7 @@ TEST(tools_common, asio_udp_provider)

TEST(tools_common, sim_net_provider)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;

Expand Down
8 changes: 4 additions & 4 deletions src/core/tests/service_api_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ TEST(core, dsn_config)

TEST(core, dsn_exlock)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;
{
Expand Down Expand Up @@ -176,7 +176,7 @@ TEST(core, dsn_exlock)

TEST(core, dsn_rwlock)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;
dsn_handle_t l = dsn_rwlock_nr_create();
Expand All @@ -190,7 +190,7 @@ TEST(core, dsn_rwlock)

TEST(core, dsn_semaphore)
{
if (dsn::service_engine::fast_instance().spec().semaphore_factory_name ==
if (dsn::service_engine::instance().spec().semaphore_factory_name ==
"dsn::tools::sim_semaphore_provider")
return;
dsn_handle_t s = dsn_semaphore_create(2);
Expand Down Expand Up @@ -283,7 +283,7 @@ TEST(core, dsn_file)

TEST(core, dsn_env)
{
if (dsn::service_engine::fast_instance().spec().tool == "simulator")
if (dsn::service_engine::instance().spec().tool == "simulator")
return;
uint64_t now1 = dsn_now_ns();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
Expand Down
Loading

0 comments on commit 78c8ffd

Please sign in to comment.