1
0
Fork 0
forked from lthn/blockchain
blockchain/contrib/epee/include/misc_language.h

688 lines
20 KiB
C
Raw Permalink Normal View History

Coverity (#28) * stratum_server: resolve CID 210144 (UNINIT_CTOR) * stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_blockchain_update_listener, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro A temporary substition for what I hope will eventually be a full-fledged exception-dispatcher (class-based, not macro). * stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_protocol_handler, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT) The potential to throw exists within guarded_critical_region_t, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, del_connection, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: move macros to *top* of file so they can be used *within* this file. * daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT) The potential to throw exists within log_space, and any paths involving the logger (including CATCH_ENTRY_*). * daemon: return cstdlib proper types in main * simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT) CID: 210082 CID: 210086 CID: 210096 CID: 210147 CID: 210149 CID: 210150 The potential to throw exists throughout various paths in main. * simplewallet: return cstdlib proper types in main * simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, and any paths involving the logger (including CATCH_ENTRY_*). * conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT) CID: 210038 CID: 210047 CID: 210108 CID: 210122 CID: 210157 The potential to throw exists throughout various paths in main. * conn_tool: return cstdlib proper types in main * miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT) The potential to throw exists within deinit, including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT) The potential to throw exists within boost microsec_clock::localtime(), and any paths involving the logger (including CATCH_ENTRY_*). * db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT) The potential to throw exists within close(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT) The potential to throw exists within several paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210064 CID: 210093 CID: 210136 CID: 210139 The potential to throw exists within m_func(), including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210072 CID: 210094 CID: 210116 CID: 210141 The potential to throw exists within m_cache.clear(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT) The potential to throw exists within shutdown(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT) The potential to throw exists within unlock(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: http_base: resolve CID 210176 (UNINIT_CTOR) * p2p: net_node: resolve CID 210173 (UNINIT_CTOR) * epee: net_helper: resolve CID 210138 (UNINIT_CTOR) * p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR) * currency_basic: resolve CID 210117 (UNINIT_CTOR) * epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR) CID: 210040 CID: 210090 CID: 210105 * simplewallet: resolve CID 210103 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR) * json_archive: resolve CID 210087 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR) * miniupnp_helper: resolve CID 210037 (UNINIT_CTOR) * crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN) * wallet2: resolve CID 210041 (CHECKED_RETURN) * epee: misc_log_ex: resolve CID 210127 (DEADCODE) * epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE) CID: 210167 CID: 210170 CID: 210180 * p2p: net_node: resolve CID 210065 (PASS_BY_VALUE) * epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE) * epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE) * epee: misc_log_ex: add NESTED_*_ENTRY macros * simplewallet: use NESTED_*_ENTRY in message_writer dtor * stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor * stratum_protocol_handler: use NESTED_*_ENTRY in dtor * lmdb_db_backend: use NESTED_*_ENTRY in dtor * epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210088 CID: 210106 CID: 210164 CID: 210179 The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: use NESTED_*_ENTRY in dtor * miniupnp_helper: use NESTED_*_ENTRY in dtor * epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor * epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors * epee: net_helper: use NESTED_*_ENTRY in dtor * epee: profile_tools: use NESTED_*_ENTRY in dtors * epee: misc_language: use NESTED_*_ENTRY in dtor * epee: syncobj: use NESTED_*_ENTRY in dtor * zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
// Copyright (c) 2019, anonimal, <anonimal@zano.org>
2018-12-27 18:50:45 +03:00
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include <limits>
#include <set>
#include <iterator>
2022-02-12 22:38:12 +03:00
#include <algorithm>
#include <functional>
2018-12-27 18:50:45 +03:00
#include <boost/thread.hpp>
#include <boost/any.hpp>
2018-12-27 18:50:45 +03:00
#include "include_base_utils.h"
#include "auto_val_init.h"
#define MARK_AS_POD_C11(type) \
namespace std \
{ \
template<> \
struct is_pod< type > \
{ \
static const bool value = true; \
}; \
}
namespace epee
{
#define STD_TRY_BEGIN() try {
#define STD_TRY_CATCH(where_, ret_val) \
} \
catch (const std::exception &e) \
{ \
LOG_ERROR("EXCEPTION: " << where_ << ", mes: "<< e.what()); \
return ret_val; \
} \
catch (...) \
{ \
LOG_ERROR("EXCEPTION: " << where_ ); \
return ret_val; \
}
2021-06-17 23:02:57 +02:00
#define STD_TRY_CATCH_LOCATION(return_val) STD_TRY_CATCH(LOCATION_SS, return_val)
2018-12-27 18:50:45 +03:00
/* helper class, to make able get namespace via decltype()::*/
template<class base_class>
class namespace_accessor: public base_class{};
#define STRINGIFY_EXPAND(s) STRINGIFY(s)
#define STRINGIFY(s) #s
namespace misc_utils
{
template<typename t_type_a, typename t_type_b>
void cast_assign_a_to_b(const t_type_a& a, t_type_b& b)
{
*static_cast<t_type_a*>(&b) = a;
}
template<class _Ty1,
class _Ty2,
class _Ty3>
struct triple
{ // store a pair of values
typedef _Ty1 first_type;
typedef _Ty2 second_type;
typedef _Ty3 third_type;
triple()
: first(), second(), third()
{ // default construct
}
triple(const _Ty1& _Val1, const _Ty2& _Val2, const _Ty3& _Val3)
: first(_Val1), second(_Val2), third(_Val3)
{ // construct from specified values
}
_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
_Ty3 third; // the second stored value
};
2018-12-27 18:50:45 +03:00
template<typename t_type>
t_type get_max_t_val(t_type t)
{
return (std::numeric_limits<t_type>::max)();
}
template<class _Ty>
bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right)
{ // apply operator< to operands
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
}
inline
bool sleep_no_w(long ms )
{
boost::this_thread::sleep(
boost::get_system_time() +
boost::posix_time::milliseconds( std::max<long>(ms,0) ) );
return true;
}
/************************************************************************/
/* */
/************************************************************************/
template<typename key, typename associated_data>
class median_helper
{
typedef std::multiset<key> ordered_items_container;
typedef std::pair<typename ordered_items_container::iterator, associated_data> queued_item_type;
typedef std::list<queued_item_type> queued_items_container;
typedef std::list<std::pair<key, associated_data> > recent_items_container;
ordered_items_container ordered_items;
queued_items_container queued_items;
recent_items_container recent_items; // this needed to have chance to roll back at least for some depth, so we keep elements removed from median window for a while
bool had_been_in_recent_items;
mutable critical_section m_lock;
typename ordered_items_container::iterator m_current_median_it;
uint64_t current_index;
virtual void handle_purge_back_item() {}
virtual void handle_add_front_item(const key& k, const associated_data& ad) {}
virtual void handle_remove_front_item(const key& k) {}
void push_item_as_recent(const key& k, const associated_data& ad)
{
CRITICAL_REGION_LOCAL(m_lock);
auto it = ordered_items.insert(k);
queued_items.push_front(queued_item_type(it, ad));
}
public:
median_helper() :had_been_in_recent_items(false)
{
m_current_median_it = ordered_items.end();
current_index = 0;
}
void clear()
{
CRITICAL_REGION_LOCAL(m_lock);
ordered_items.clear();
queued_items.clear();
recent_items.clear();
had_been_in_recent_items = false;
m_current_median_it = ordered_items.end();
current_index = 0;
}
void push_item(const key& k, const associated_data& ad)
{
CRITICAL_REGION_LOCAL(m_lock);
auto it = ordered_items.insert(k);
queued_items.push_back(queued_item_type(it, ad));
handle_add_front_item(k, ad);
}
void pop_item()
{
CRITICAL_REGION_LOCAL(m_lock);
if (!queued_items.empty())
{
auto it = queued_items.back().first;
handle_remove_front_item(*it);
ordered_items.erase(it);
queued_items.pop_back();
}
}
/*
cb(key, associated_data) - enumerating while result is false
when returned true - clean items behind and move it to recent_items
cb_final_remove(key, associated_data) - for every element in recent_items if returned false - element removed forever
*/
template<class cb_t, class cb_t2>
bool scan_items(cb_t cb, cb_t2 cb_final_remove)
{
CRITICAL_REGION_LOCAL(m_lock);
//process median window items
for (auto it = queued_items.begin(); it != queued_items.end(); it++)
{
if (cb(*it->first, it->second))
{
//stop element, remove all items before this
for (auto clean_it = queued_items.begin(); clean_it != it; clean_it++)
{
//std::pair<key, associated_data> p(*it->first, it->second);
recent_items.push_back(std::make_pair(*clean_it->first, clean_it->second));
had_been_in_recent_items = true;
ordered_items.erase(clean_it->first);
}
queued_items.erase(queued_items.begin(), it);
break;
}
}
//process recent items front part (put back to median window set if needed)
for (auto it = recent_items.rbegin(); it != recent_items.rend();)
{
if (!cb(it->first, it->second))
break;//element should stay in recent
//element should be back to median window
this->push_item_as_recent(it->first, it->second);
it = typename recent_items_container::reverse_iterator(recent_items.erase((++it).base())); // remove *it and advance 'it' by 1
}
//process recent items back part (remove outdated elements)
while (recent_items.size() && !cb_final_remove(recent_items.begin()->first, recent_items.begin()->second))
{
recent_items.erase(recent_items.begin());
handle_purge_back_item();
}
//detect if recent_items exhausted
if (!recent_items.size() && had_been_in_recent_items)
{
LOG_PRINT_RED_L0("[MEDIAN_HELPER]: recent_items exhausted, need to rebuild median from scratch");
return false;
}
return true;
}
uint64_t get_median() const
{
CRITICAL_REGION_LOCAL(m_lock);
if (!ordered_items.size())
return 0;
size_t n = ordered_items.size() / 2;
//std::sort(v.begin(), v.end());
auto n_it = std::next(ordered_items.begin(), n);
//nth_element(v.begin(), v.begin()+n-1, v.end());
if (ordered_items.size() % 2)
{//1, 3, 5...
return *n_it;
}
else
{//2, 4, 6...
auto n_it_sub = n_it;
--n_it_sub;
return (*n_it_sub + *n_it) / 2;
}
}
2024-01-02 21:57:43 +01:00
uint64_t get_avg() const
{
CRITICAL_REGION_LOCAL(m_lock);
if (!queued_items.size())
return 0;
uint64_t summ = 0;
for (const auto& item : queued_items)
{
summ += *item.first;
}
return summ / queued_items.size();
}
2018-12-27 18:50:45 +03:00
template<typename key_t, typename associated_data_t>
friend std::ostream & operator<< (std::ostream &out, median_helper<key_t, associated_data_t> const &mh);
}; // class median_helper
template<typename key_t, typename associated_data_t>
std::ostream & operator<< (std::ostream &s, median_helper<key_t, associated_data_t> const &mh)
{
s << "median_helper<" << typeid(key_t).name() << ", " << typeid(associated_data_t).name() << "> instance 0x" << &mh << ENDL
<< " ordered_items: " << mh.ordered_items.size() << ENDL
<< " queued_items: " << mh.queued_items.size() << ENDL
<< " recent_items: " << mh.recent_items.size() << ENDL
<< " had_been_in_recent_items: " << mh.had_been_in_recent_items << ENDL;
return s;
}
/************************************************************************/
/* */
/************************************************************************/
2023-12-27 14:06:23 +01:00
template<typename container_t>
typename container_t::value_type median(container_t &v)
2018-12-27 18:50:45 +03:00
{
2023-12-27 16:44:15 +01:00
typename container_t::value_type median{};
2018-12-27 18:50:45 +03:00
if(v.empty())
2023-12-27 14:06:23 +01:00
return median;
2018-12-27 18:50:45 +03:00
if(v.size() == 1)
return v[0];
2023-12-27 14:06:23 +01:00
auto median_it = v.begin() + v.size() / 2;
std::nth_element(v.begin(), median_it, v.end());
median = *median_it;
if (v.size() % 2 == 0)
{
auto max_it = std::max_element(v.begin(), median_it); // it's garanteed that after nth_element() the necessary element is in this interval
median = (median + *max_it) / 2; // average of [size/2-1] and [size/2] elements
2018-12-27 18:50:45 +03:00
}
2023-12-27 14:06:23 +01:00
return median;
2018-12-27 18:50:45 +03:00
}
/************************************************************************/
/* */
/************************************************************************/
struct call_befor_die_base
{
virtual ~call_befor_die_base(){}
};
typedef boost::shared_ptr<call_befor_die_base> auto_scope_leave_caller;
template<class t_scope_leave_handler>
struct call_befor_die: public call_befor_die_base
{
t_scope_leave_handler m_func;
call_befor_die(t_scope_leave_handler f):m_func(f)
{}
~call_befor_die()
{
Coverity (#28) * stratum_server: resolve CID 210144 (UNINIT_CTOR) * stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_blockchain_update_listener, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro A temporary substition for what I hope will eventually be a full-fledged exception-dispatcher (class-based, not macro). * stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_protocol_handler, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT) The potential to throw exists within guarded_critical_region_t, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, del_connection, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: move macros to *top* of file so they can be used *within* this file. * daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT) The potential to throw exists within log_space, and any paths involving the logger (including CATCH_ENTRY_*). * daemon: return cstdlib proper types in main * simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT) CID: 210082 CID: 210086 CID: 210096 CID: 210147 CID: 210149 CID: 210150 The potential to throw exists throughout various paths in main. * simplewallet: return cstdlib proper types in main * simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, and any paths involving the logger (including CATCH_ENTRY_*). * conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT) CID: 210038 CID: 210047 CID: 210108 CID: 210122 CID: 210157 The potential to throw exists throughout various paths in main. * conn_tool: return cstdlib proper types in main * miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT) The potential to throw exists within deinit, including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT) The potential to throw exists within boost microsec_clock::localtime(), and any paths involving the logger (including CATCH_ENTRY_*). * db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT) The potential to throw exists within close(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT) The potential to throw exists within several paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210064 CID: 210093 CID: 210136 CID: 210139 The potential to throw exists within m_func(), including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210072 CID: 210094 CID: 210116 CID: 210141 The potential to throw exists within m_cache.clear(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT) The potential to throw exists within shutdown(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT) The potential to throw exists within unlock(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: http_base: resolve CID 210176 (UNINIT_CTOR) * p2p: net_node: resolve CID 210173 (UNINIT_CTOR) * epee: net_helper: resolve CID 210138 (UNINIT_CTOR) * p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR) * currency_basic: resolve CID 210117 (UNINIT_CTOR) * epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR) CID: 210040 CID: 210090 CID: 210105 * simplewallet: resolve CID 210103 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR) * json_archive: resolve CID 210087 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR) * miniupnp_helper: resolve CID 210037 (UNINIT_CTOR) * crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN) * wallet2: resolve CID 210041 (CHECKED_RETURN) * epee: misc_log_ex: resolve CID 210127 (DEADCODE) * epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE) CID: 210167 CID: 210170 CID: 210180 * p2p: net_node: resolve CID 210065 (PASS_BY_VALUE) * epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE) * epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE) * epee: misc_log_ex: add NESTED_*_ENTRY macros * simplewallet: use NESTED_*_ENTRY in message_writer dtor * stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor * stratum_protocol_handler: use NESTED_*_ENTRY in dtor * lmdb_db_backend: use NESTED_*_ENTRY in dtor * epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210088 CID: 210106 CID: 210164 CID: 210179 The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: use NESTED_*_ENTRY in dtor * miniupnp_helper: use NESTED_*_ENTRY in dtor * epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor * epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors * epee: net_helper: use NESTED_*_ENTRY in dtor * epee: profile_tools: use NESTED_*_ENTRY in dtors * epee: misc_language: use NESTED_*_ENTRY in dtor * epee: syncobj: use NESTED_*_ENTRY in dtor * zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
NESTED_TRY_ENTRY();
2018-12-27 18:50:45 +03:00
m_func();
Coverity (#28) * stratum_server: resolve CID 210144 (UNINIT_CTOR) * stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_blockchain_update_listener, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro A temporary substition for what I hope will eventually be a full-fledged exception-dispatcher (class-based, not macro). * stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, remove_protocol_handler, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT) The potential to throw exists within guarded_critical_region_t, and any paths involving the logger (including CATCH_ENTRY_*). * epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT) The potential to throw exists within the logger, del_connection, and any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: move macros to *top* of file so they can be used *within* this file. * daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT) The potential to throw exists within log_space, and any paths involving the logger (including CATCH_ENTRY_*). * daemon: return cstdlib proper types in main * simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT) CID: 210082 CID: 210086 CID: 210096 CID: 210147 CID: 210149 CID: 210150 The potential to throw exists throughout various paths in main. * simplewallet: return cstdlib proper types in main * simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, and any paths involving the logger (including CATCH_ENTRY_*). * conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT) CID: 210038 CID: 210047 CID: 210108 CID: 210122 CID: 210157 The potential to throw exists throughout various paths in main. * conn_tool: return cstdlib proper types in main * miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT) The potential to throw exists within deinit, including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT) The potential to throw exists within boost microsec_clock::localtime(), and any paths involving the logger (including CATCH_ENTRY_*). * db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT) The potential to throw exists within close(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT) The potential to throw exists within several paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210064 CID: 210093 CID: 210136 CID: 210139 The potential to throw exists within m_func(), including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210072 CID: 210094 CID: 210116 CID: 210141 The potential to throw exists within m_cache.clear(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT) The potential to throw exists within shutdown(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT) The potential to throw exists within unlock(), including any paths involving the logger (including CATCH_ENTRY_*). * epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT) The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * epee: http_base: resolve CID 210176 (UNINIT_CTOR) * p2p: net_node: resolve CID 210173 (UNINIT_CTOR) * epee: net_helper: resolve CID 210138 (UNINIT_CTOR) * p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR) * currency_basic: resolve CID 210117 (UNINIT_CTOR) * epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR) CID: 210040 CID: 210090 CID: 210105 * simplewallet: resolve CID 210103 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR) * json_archive: resolve CID 210087 (UNINIT_CTOR) * epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR) * miniupnp_helper: resolve CID 210037 (UNINIT_CTOR) * crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN) * wallet2: resolve CID 210041 (CHECKED_RETURN) * epee: misc_log_ex: resolve CID 210127 (DEADCODE) * epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE) CID: 210167 CID: 210170 CID: 210180 * p2p: net_node: resolve CID 210065 (PASS_BY_VALUE) * epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE) * epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE) * epee: misc_log_ex: add NESTED_*_ENTRY macros * simplewallet: use NESTED_*_ENTRY in message_writer dtor * stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor * stratum_protocol_handler: use NESTED_*_ENTRY in dtor * lmdb_db_backend: use NESTED_*_ENTRY in dtor * epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT) CID: 210088 CID: 210106 CID: 210164 CID: 210179 The potential to throw exists within various paths, including any paths involving the logger (including CATCH_ENTRY_*). * db_abstract_accessor: use NESTED_*_ENTRY in dtor * miniupnp_helper: use NESTED_*_ENTRY in dtor * epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor * epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors * epee: net_helper: use NESTED_*_ENTRY in dtor * epee: profile_tools: use NESTED_*_ENTRY in dtors * epee: misc_language: use NESTED_*_ENTRY in dtor * epee: syncobj: use NESTED_*_ENTRY in dtor * zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
NESTED_CATCH_ENTRY(__func__);
2018-12-27 18:50:45 +03:00
}
};
template<class t_scope_leave_handler>
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
{
auto_scope_leave_caller slc(new call_befor_die<t_scope_leave_handler>(f));
return slc;
}
#define ON_FUNC_EXIT misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler
2018-12-27 18:50:45 +03:00
template< typename t_contaner, typename t_redicate>
void erase_if( t_contaner& items, const t_redicate& predicate )
{
for(auto it = items.begin(); it != items.end(); )
{
if( predicate(*it) )
it = items.erase(it);
else
++it;
}
};
/************************************************************************/
/* */
/************************************************************************/
struct call_basic
{
virtual void do_call(){};
};
template<typename param_t>
struct call_basic_param
{
virtual void do_call(param_t& p) {};
};
2018-12-27 18:50:45 +03:00
template<typename t_callback>
struct call_specific: public call_basic
{
call_specific(t_callback cb):m_cb(cb)
{}
virtual void do_call()
{
m_cb();
}
private:
t_callback m_cb;
};
template<typename param_t, typename t_callback>
struct call_specific_param : public call_basic_param<param_t>
{
call_specific_param(t_callback cb) :m_cb(cb)
{}
2023-08-28 21:27:33 +02:00
virtual void do_call(const param_t& p)
{
m_cb(p);
}
private:
t_callback m_cb;
};
2018-12-27 18:50:45 +03:00
template<typename t_callback>
auto build_abstract_callback(t_callback cb) -> std::shared_ptr<call_basic>
{
return std::shared_ptr<call_basic>(new call_specific<t_callback>(cb));
}
template<typename param_t, typename t_callback>
auto build_abstract_callback_param(t_callback cb) -> std::shared_ptr<call_basic_param<param_t>>
{
return std::shared_ptr<call_basic_param<param_t>>(new call_specific_param<param_t, t_callback>(cb));
}
2018-12-27 18:50:45 +03:00
template<class callback_type>
bool static_initializer(callback_type cb)
{
return cb();
};
template<class t_container_type>
typename t_container_type::mapped_type& get_or_insert_value_initialized(t_container_type& container, const typename t_container_type::key_type& key)
{
auto it = container.find(key);
if (it != container.end())
{
return it->second;
}
auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type())));
return res.first->second;
}
template<class t_container_type>
typename t_container_type::iterator it_get_or_insert_value_initialized(t_container_type& container, const typename t_container_type::key_type& key)
{
auto it = container.find(key);
if (it != container.end())
{
return it;
}
auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type())));
return res.first;
}
class events_dispatcher
{
public:
template<typename param_t>
struct callback_entry
{
2023-08-28 20:31:27 +02:00
std::shared_ptr<epee::misc_utils::call_basic_param<const param_t> > m_cb;
};
std::map<std::type_index, boost::any> m_callbacks;
template<typename param_t, typename callback_t>
void SUBSCIRBE_DEBUG_EVENT(callback_t cb)
{
std::type_index ti = typeid(param_t);
auto it = m_callbacks.find(ti);
if (it != m_callbacks.end())
{
throw std::runtime_error("Handler for this type already registered");
}
2023-08-28 20:31:27 +02:00
callback_entry<const param_t> cb_entry = { epee::misc_utils::build_abstract_callback_param<const param_t>(cb) };
m_callbacks[ti] = cb_entry;
}
template<typename param_t>
void UNSUBSCRIBE_DEBUG_EVENT()
{
std::type_index ti = typeid(param_t);
auto it = m_callbacks.find(ti);
if (it != m_callbacks.end())
{
m_callbacks.erase(it);
}
}
void UNSUBSCRIBE_ALL()
{
m_callbacks.clear();
}
template<typename param_t>
2023-08-28 20:31:27 +02:00
void RAISE_DEBUG_EVENT(const param_t& p)
{
std::type_index ti = typeid(param_t);
auto it = m_callbacks.find(ti);
if (it != m_callbacks.end())
{
2023-08-28 20:31:27 +02:00
callback_entry<const param_t >* pcallback_entry = boost::any_cast<callback_entry<const param_t >>(&it->second);
if (!pcallback_entry)
{
throw std::runtime_error("Unexpected error: registered tipe holding something else in boost::eny");
}
pcallback_entry->m_cb->do_call(p);
}
}
};
template<typename key, typename expiration_type>
struct expirating_set
{
typedef std::set<key> main_set;
main_set m_set;
std::multimap<expiration_type, typename main_set::iterator> m_expirations;
const main_set& get_set()
{
return m_set;
}
void add(const key& k, const expiration_type& e)
{
auto res = m_set.insert(k);
m_expirations.insert({ e, res.first });
}
void remove_if_expiration_less_than(const expiration_type& e)
{
while(m_expirations.size() && m_expirations.begin()->first < e)
{
2024-04-06 17:22:44 +02:00
m_set.erase(m_expirations.begin()->second);
m_expirations.erase(m_expirations.begin());
}
}
};
2024-04-06 17:22:44 +02:00
template<typename key, typename expiration_type, typename value_type>
struct expirating_map
{
typedef std::map<key, value_type> main_map;
main_map m_map;
std::multimap<expiration_type, typename main_map::iterator> m_expirations;
const main_map& get_map()
{
return m_map;
}
void add(const key& k, const value_type& v, const expiration_type& e)
{
auto res = m_map.insert(k, v);
m_expirations.insert({ e, res.first });
}
void remove_if_expiration_less_than(const expiration_type& e)
{
while (m_expirations.size() && m_expirations.begin()->first < e)
{
2024-04-06 18:54:02 +02:00
m_map.erase(m_expirations.begin()->second);
2024-04-06 17:22:44 +02:00
m_expirations.erase(m_expirations.begin());
}
}
template <class t_archive>
inline void serialize(t_archive& a, const unsigned int ver)
{
std::vector<std::tuple<key, value_type, expiration_type> > items;
if constexpr (t_archive::is_saving::value)
{
for (const auto& item: m_expirations)
{
items.resize(items.size + 1);
std::get<2>(items.back()) = item.first;
std::get<0>(items.back()) = item.second.first;
std::get<1>(items.back()) = item.second.second;
}
}
a & items;
if constexpr (!t_archive::is_saving::value)
{
for (const auto& item : items)
{
this->add(std::get<0>(item), std::get<1>(item), std::get<2>(item));
items.resize(items.size + 1);
std::get<2>(items.back()) = item.first;
std::get<0>(items.back()) = item.second.first;
std::get<1>(items.back()) = item.second.second;
}
}
}
};
2025-05-21 04:32:16 +03:00
// helper class mainly intended for using with std::atomic to repair copy-construction in classes where std::atomic is aggregated
template<typename parent_t>
struct void_copy : public parent_t
{
void_copy() = default;
void_copy(void_copy&&) noexcept = default;
void_copy& operator=(void_copy&&) noexcept = default;
void_copy(const void_copy&) : parent_t{} {}
void_copy& operator=(const void_copy&) { return *this; }
};
} // namespace misc_utils
} // namespace epee
2018-12-27 18:50:45 +03:00
template<typename T>
std::ostream& print_container_content(std::ostream& out, const T& v);
namespace std
2018-12-27 18:50:45 +03:00
{
template<typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v)
{
return print_container_content(out, v);
}
template<typename T>
std::ostream& operator<< (std::ostream& out, const std::list<T>& v)
{
return print_container_content(out, v);
}
} // namespace std
2018-12-27 18:50:45 +03:00
template<typename T>
std::ostream& print_container_content(std::ostream& out, const T& v)
{
out << "[";
if (!v.size())
{
out << "]";
return out;
}
typename T::const_iterator last_it = --v.end();
for (typename T::const_iterator it = v.begin(); it != v.end(); it++)
{
out << *it;
if (it != last_it)
out << ", ";
}
out << "]";
return out;
}