Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

valgrind: use function-local initialization to implement singleton #174

Merged
merged 6 commits into from
Oct 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 &);
Copy link
Contributor

@shengofsun shengofsun Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nocopyable的feature没了。毕竟这是个utility库,我们还是严谨些吧。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已改

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