File: ze_singleton.h

package info (click to toggle)
level-zero 1.26.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,468 kB
  • sloc: cpp: 130,327; ansic: 16,197; python: 9,824; makefile: 4
file content (80 lines) | stat: -rw-r--r-- 2,592 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 *
 * Copyright (C) 2019-2025 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 *
 */
#pragma once
#include <memory>
#include <unordered_map>
#include <mutex>
#include <iostream>

//////////////////////////////////////////////////////////////////////////
/// a abstract factory for creation of singleton objects
template<typename _singleton_t, typename _key_t>
class singleton_factory_t
{
protected:
    using singleton_t = _singleton_t;
    using key_t = typename std::conditional<std::is_pointer<_key_t>::value, size_t, _key_t>::type;

    using ptr_t = std::unique_ptr < singleton_t >;
    using map_t = std::unordered_map < key_t, ptr_t >;

    std::mutex mut; ///< lock for thread-safety
    map_t map;      ///< single instance of singleton for each unique key

    //////////////////////////////////////////////////////////////////////////
    /// extract the key from parameter list and if necessary, convert type
    template<typename... Ts>
    key_t getKey( _key_t _key, Ts&&... _params )
    {
        return reinterpret_cast<key_t>( _key );
    }

public:
    //////////////////////////////////////////////////////////////////////////
    /// default ctor/dtor
    singleton_factory_t() = default;
    ~singleton_factory_t() = default;

    //////////////////////////////////////////////////////////////////////////
    /// gets a pointer to a unique instance of singleton
    /// if no instance exists, then creates a new instance
    /// the params are forwarded to the ctor of the singleton
    /// the first parameter must be the unique identifier of the instance
    template<typename... Ts>
    _singleton_t* getInstance( Ts&&... _params )
    {
        auto key = getKey( std::forward<Ts>( _params )... );

        if(key == 0) // No zero keys allowed in map
            return static_cast<_singleton_t*>(0);

        std::lock_guard<std::mutex> lk( mut );
        auto iter = map.find( key );

        if( map.end() == iter )
        {
            auto ptr = std::make_unique<singleton_t>( std::forward<Ts>( _params )... );
            iter = map.emplace( key, std::move( ptr ) ).first;
        }
        return iter->second.get();
    }

    bool hasInstance( _key_t _key )
    {
        std::lock_guard<std::mutex> lk( mut );
        return map.find( getKey( _key ) ) != map.end();
    }

    //////////////////////////////////////////////////////////////////////////
    /// once the key is no longer valid, release the singleton
    void release( _key_t _key )
    {
        std::lock_guard<std::mutex> lk( mut );
        map.erase( getKey( _key ) );
    }
};