Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:26

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
0012 //
0013 //  boost/detail/lightweight_thread.hpp
0014 //
0015 //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
0016 //  Copyright (c) 2008 Peter Dimov
0017 //
0018 //  Distributed under the Boost Software License, Version 1.0.
0019 //  See accompanying file LICENSE_1_0.txt or copy at
0020 //  http://www.boost.org/LICENSE_1_0.txt
0021 
0022 #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
0023 #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
0024 
0025 #ifndef BOOST_CONFIG_HPP
0026 #  include <boost/config.hpp>
0027 #endif
0028 #
0029 #if defined(BOOST_HAS_PRAGMA_ONCE)
0030 #  pragma once
0031 #endif
0032 
0033 #include <boost/interprocess/detail/config_begin.hpp>
0034 #include <boost/interprocess/detail/workaround.hpp>
0035 #include <boost/interprocess/streams/bufferstream.hpp>
0036 #include <cstddef>
0037 #include <ostream>
0038 
0039 #if defined(BOOST_INTERPROCESS_WINDOWS)
0040 #  include <boost/interprocess/detail/win32_api.hpp>
0041 #  include <boost/winapi/thread.hpp>
0042 #else
0043 #  include <pthread.h>
0044 #  include <unistd.h>
0045 #  include <sched.h>
0046 #  include <time.h>
0047 #  ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
0048       //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
0049       //others (FreeBSD & Darwin) need sys/types.h
0050 #     include <sys/types.h>
0051 #     include <sys/param.h>
0052 #     include <sys/sysctl.h>
0053 #  endif
0054 #if defined(__VXWORKS__) 
0055 #include <vxCpuLib.h>
0056 #endif 
0057 //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
0058 //Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and
0059 //CLOCK_MONOTONIC_RAW and no clock_gettime.
0060 #  if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
0061 #     include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
0062 #     define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0063 #  elif defined(CLOCK_MONOTONIC_PRECISE)   //BSD
0064 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
0065 #  elif defined(CLOCK_MONOTONIC_RAW)     //Linux
0066 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
0067 #  elif defined(CLOCK_HIGHRES)           //Solaris
0068 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
0069 #  elif defined(CLOCK_MONOTONIC)         //POSIX (AIX, BSD, Linux, Solaris)
0070 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
0071 #  else
0072 #     error "No high resolution steady clock in your system, please provide a patch"
0073 #  endif
0074 #endif
0075 
0076 namespace boost {
0077 namespace interprocess {
0078 namespace ipcdetail{
0079 
0080 #if defined (BOOST_INTERPROCESS_WINDOWS)
0081 
0082 typedef unsigned long OS_process_id_t;
0083 typedef unsigned long OS_thread_id_t;
0084 struct OS_thread_t
0085 {
0086    OS_thread_t()
0087       : m_handle()
0088    {}
0089 
0090    
0091    void* handle() const
0092    {  return m_handle;  }
0093 
0094    void* m_handle;
0095 };
0096 
0097 typedef OS_thread_id_t OS_systemwide_thread_id_t;
0098 
0099 //process
0100 inline OS_process_id_t get_current_process_id()
0101 {  return winapi::get_current_process_id();  }
0102 
0103 inline OS_process_id_t get_invalid_process_id()
0104 {  return OS_process_id_t(0);  }
0105 
0106 //thread
0107 inline OS_thread_id_t get_current_thread_id()
0108 {  return winapi::get_current_thread_id();  }
0109 
0110 inline OS_thread_id_t get_invalid_thread_id()
0111 {  return OS_thread_id_t(0xffffffff);  }
0112 
0113 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
0114 {  return id1 == id2;  }
0115 
0116 //return the system tick in ns
0117 inline unsigned long get_system_tick_ns()
0118 {
0119    unsigned long curres, ignore1, ignore2;
0120    winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0121    //Windows API returns the value in hundreds of ns
0122    return (curres - 1ul)*100ul;
0123 }
0124 
0125 //return the system tick in us
0126 inline unsigned long get_system_tick_us()
0127 {
0128    unsigned long curres, ignore1, ignore2;
0129    winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0130    //Windows API returns the value in hundreds of ns
0131    return (curres - 1ul)/10ul + 1ul;
0132 }
0133 
0134 typedef unsigned __int64 OS_highres_count_t;
0135 
0136 inline unsigned long get_system_tick_in_highres_counts()
0137 {
0138    __int64 freq;
0139    unsigned long curres, ignore1, ignore2;
0140    winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0141    //Frequency in counts per second
0142    if(!winapi::query_performance_frequency(&freq)){
0143       //Tick resolution in ms
0144       return (curres-1ul)/10000ul + 1ul;
0145    }
0146    else{
0147       //In femtoseconds
0148       __int64 count_fs    = (1000000000000000LL - 1LL)/freq + 1LL;
0149       __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
0150       return static_cast<unsigned long>(tick_counts);
0151    }
0152 }
0153 
0154 inline OS_highres_count_t get_current_system_highres_count()
0155 {
0156    __int64 count;
0157    if(!winapi::query_performance_counter(&count)){
0158       count = winapi::get_tick_count();
0159    }
0160    return (OS_highres_count_t)count;
0161 }
0162 
0163 inline void zero_highres_count(OS_highres_count_t &count)
0164 {  count = 0;  }
0165 
0166 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0167 {  return count == 0;  }
0168 
0169 template <class Ostream>
0170 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0171 {
0172    ostream << count;
0173    return ostream;
0174 }
0175 
0176 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0177 {  return l - r;  }
0178 
0179 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0180 {  return l < r;  }
0181 
0182 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0183 {  return l < static_cast<OS_highres_count_t>(r);  }
0184 
0185 inline void thread_sleep_tick()
0186 {  winapi::sleep_tick();   }
0187 
0188 inline void thread_yield()
0189 {  winapi::sched_yield();  }
0190 
0191 inline void thread_sleep(unsigned int ms)
0192 {  winapi::sleep(ms);  }
0193 
0194 //systemwide thread
0195 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
0196 {
0197    return get_current_thread_id();
0198 }
0199 
0200 inline void systemwide_thread_id_copy
0201    (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
0202 {
0203    to = from;
0204 }
0205 
0206 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
0207 {
0208    return equal_thread_id(id1, id2);
0209 }
0210 
0211 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
0212 {
0213    return get_invalid_thread_id();
0214 }
0215 
0216 inline long double get_current_process_creation_time()
0217 {
0218    winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
0219 
0220    winapi::get_process_times
0221       ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
0222 
0223    typedef long double ldouble_t;
0224    const ldouble_t resolution = (100.0l/1000000000.0l);
0225    return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
0226               CreationTime.dwLowDateTime*resolution;
0227 }
0228 
0229 inline unsigned int get_num_cores()
0230 {
0231    winapi::interprocess_system_info sysinfo;
0232    winapi::get_system_info( &sysinfo );
0233    //in Windows dw is long which is equal in bits to int
0234    return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
0235 }
0236 
0237 #else    //#if defined (BOOST_INTERPROCESS_WINDOWS)
0238 
0239 typedef pthread_t OS_thread_t;
0240 typedef pthread_t OS_thread_id_t;
0241 typedef pid_t     OS_process_id_t;
0242 
0243 struct OS_systemwide_thread_id_t
0244 {
0245    OS_systemwide_thread_id_t()
0246       :  pid(), tid()
0247    {}
0248 
0249    OS_systemwide_thread_id_t(pid_t p, pthread_t t)
0250       :  pid(p), tid(t)
0251    {}
0252 
0253    OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
0254       :  pid(x.pid), tid(x.tid)
0255    {}
0256 
0257    OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
0258       :  pid(x.pid), tid(x.tid)
0259    {}
0260 
0261    OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
0262    {  pid = x.pid;   tid = x.tid;   return *this;   }
0263 
0264    OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
0265    {  pid = x.pid;   tid = x.tid;   return *this;  }
0266 
0267    void operator=(const OS_systemwide_thread_id_t &x) volatile
0268    {  pid = x.pid;   tid = x.tid;   }
0269 
0270    pid_t       pid;
0271    pthread_t   tid;
0272 };
0273 
0274 inline void systemwide_thread_id_copy
0275    (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
0276 {
0277    to.pid = from.pid;
0278    to.tid = from.tid;
0279 }
0280 
0281 //process
0282 inline OS_process_id_t get_current_process_id()
0283 {  return ::getpid();  }
0284 
0285 inline OS_process_id_t get_invalid_process_id()
0286 {  return pid_t(0);  }
0287 
0288 //thread
0289 inline OS_thread_id_t get_current_thread_id()
0290 {  return ::pthread_self();  }
0291 
0292 inline OS_thread_id_t get_invalid_thread_id()
0293 {
0294    static pthread_t invalid_id;
0295    return invalid_id;
0296 }
0297 
0298 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
0299 {  return 0 != pthread_equal(id1, id2);  }
0300 
0301 inline void thread_yield()
0302 {  ::sched_yield();  }
0303 
0304 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0305 typedef struct timespec OS_highres_count_t;
0306 #else
0307 typedef unsigned long long OS_highres_count_t;
0308 #endif
0309 
0310 inline unsigned long get_system_tick_ns()
0311 {
0312    #ifdef _SC_CLK_TCK
0313    long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec
0314    if(ticks_per_second <= 0){   //Try a typical value on error
0315       ticks_per_second = 100;
0316    }
0317    return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
0318    #else
0319       #error "Can't obtain system tick value for your system, please provide a patch"
0320    #endif
0321 }
0322 
0323 inline unsigned long get_system_tick_in_highres_counts()
0324 {
0325    #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0326    return get_system_tick_ns();
0327    #else
0328    mach_timebase_info_data_t info;
0329    mach_timebase_info(&info);
0330             //ns
0331    return static_cast<unsigned long>
0332    (
0333       static_cast<double>(get_system_tick_ns())
0334          / (static_cast<double>(info.numer) / info.denom)
0335    );
0336    #endif
0337 }
0338 
0339 //return system ticks in us
0340 inline unsigned long get_system_tick_us()
0341 {
0342    return (get_system_tick_ns()-1)/1000ul + 1ul;
0343 }
0344 
0345 inline OS_highres_count_t get_current_system_highres_count()
0346 {
0347    #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
0348       struct timespec count;
0349       ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
0350       return count;
0351    #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
0352       return ::mach_absolute_time();
0353    #endif
0354 }
0355 
0356 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0357 
0358 inline void zero_highres_count(OS_highres_count_t &count)
0359 {  count.tv_sec = 0; count.tv_nsec = 0;  }
0360 
0361 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0362 {  return count.tv_sec == 0 && count.tv_nsec == 0;  }
0363 
0364 template <class Ostream>
0365 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0366 {
0367    ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
0368    return ostream;
0369 }
0370 
0371 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0372 {
0373    OS_highres_count_t res;
0374 
0375    if (l.tv_nsec < r.tv_nsec){
0376       res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
0377       res.tv_sec  = l.tv_sec - 1 - r.tv_sec;
0378    }
0379    else{
0380       res.tv_nsec = l.tv_nsec - r.tv_nsec;
0381       res.tv_sec  = l.tv_sec - r.tv_sec;
0382    }
0383 
0384    return res;
0385 }
0386 
0387 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0388 {  return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec);  }
0389 
0390 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0391 {  return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r);  }
0392 
0393 #else
0394 
0395 inline void zero_highres_count(OS_highres_count_t &count)
0396 {  count = 0;  }
0397 
0398 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0399 {  return count == 0;  }
0400 
0401 template <class Ostream>
0402 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0403 {
0404    ostream << count ;
0405    return ostream;
0406 }
0407 
0408 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0409 {  return l - r;  }
0410 
0411 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0412 {  return l < r;  }
0413 
0414 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0415 {  return l < static_cast<OS_highres_count_t>(r);  }
0416 
0417 #endif
0418 
0419 inline void thread_sleep_tick()
0420 {
0421    struct timespec rqt;
0422    //Sleep for the half of the tick time
0423    rqt.tv_sec  = 0;
0424    rqt.tv_nsec = (long)get_system_tick_ns()/2;
0425    ::nanosleep(&rqt, 0);
0426 }
0427 
0428 inline void thread_sleep(unsigned int ms)
0429 {
0430    struct timespec rqt;
0431    rqt.tv_sec = ms/1000u;
0432    rqt.tv_nsec = (ms%1000u)*1000000u;
0433    ::nanosleep(&rqt, 0);
0434 }
0435 
0436 //systemwide thread
0437 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
0438 {
0439    return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
0440 }
0441 
0442 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
0443 {
0444    return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
0445 }
0446 
0447 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
0448 {
0449    return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
0450 }
0451 
0452 inline long double get_current_process_creation_time()
0453 { return 0.0L; }
0454 
0455 inline unsigned int get_num_cores()
0456 {
0457    #ifdef _SC_NPROCESSORS_ONLN
0458       long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
0459       // sysconf returns -1 if the name is invalid, the option does not exist or
0460       // does not have a definite limit.
0461       // if sysconf returns some other negative number, we have no idea
0462       // what is going on. Default to something safe.
0463       if(cores <= 0){
0464          return 1;
0465       }
0466       //Check for overflow (unlikely)
0467       else if(static_cast<unsigned long>(cores) >=
0468               static_cast<unsigned long>(static_cast<unsigned int>(-1))){
0469          return static_cast<unsigned int>(-1);
0470       }
0471       else{
0472          return static_cast<unsigned int>(cores);
0473       }
0474    #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
0475       int request[2] = { CTL_HW, HW_NCPU };
0476       int num_cores;
0477       std::size_t result_len = sizeof(num_cores);
0478       if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
0479          //Return a safe value
0480          return 1;
0481       }
0482       else{
0483          return static_cast<unsigned int>(num_cores);
0484       }
0485    #elif defined(__VXWORKS__)
0486       cpuset_t set =  ::vxCpuEnabledGet();
0487     #ifdef __DCC__
0488       int i;
0489       for( i = 0; set; ++i)
0490           {
0491                set &= set -1;
0492           }
0493       return(i);
0494     #else  
0495       return (__builtin_popcount(set) );
0496     #endif  
0497    #endif
0498 }
0499 
0500 inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
0501 {  return pthread_create(thread, 0, start_routine, arg); }
0502 
0503 inline void thread_join(OS_thread_t thread)
0504 {  (void)pthread_join(thread, 0);  }
0505 
0506 #endif   //#if defined (BOOST_INTERPROCESS_WINDOWS)
0507 
0508 typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
0509 
0510 inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
0511 {
0512    bufferstream bstream(pid_str, sizeof(pid_str));
0513    bstream << pid << std::ends;
0514 }
0515 
0516 inline void get_pid_str(pid_str_t &pid_str)
0517 {  get_pid_str(pid_str, get_current_process_id());  }
0518 
0519 #if defined(BOOST_INTERPROCESS_WINDOWS)
0520 
0521 inline int thread_create( OS_thread_t * thread, boost::ipwinapiext::LPTHREAD_START_ROUTINE_ start_routine, void* arg )
0522 {
0523    void* h = boost::ipwinapiext::CreateThread(0, 0, start_routine, arg, 0, 0);
0524 
0525    if( h != 0 ){
0526       thread->m_handle = h;
0527       return 0;
0528    }
0529    else{
0530       return 1;
0531    }
0532 }
0533 
0534 inline void thread_join( OS_thread_t thread)
0535 {
0536    winapi::wait_for_single_object( thread.handle(), winapi::infinite_time );
0537    winapi::close_handle( thread.handle() );
0538 }
0539 
0540 #endif
0541 
0542 class abstract_thread
0543 {
0544    public:
0545    virtual ~abstract_thread() {}
0546    virtual void run() = 0;
0547 };
0548 
0549 template<class T>
0550 class os_thread_func_ptr_deleter
0551 {
0552    public:
0553    explicit os_thread_func_ptr_deleter(T* p)
0554       : m_p(p)
0555    {}
0556 
0557    T *release()
0558    {  T *p = m_p; m_p = 0; return p;  }
0559 
0560    T *get() const
0561    {  return m_p;  }
0562 
0563    T *operator ->() const
0564    {  return m_p;  }
0565 
0566    ~os_thread_func_ptr_deleter()
0567    {  delete m_p; }
0568 
0569    private:
0570    T *m_p;
0571 };
0572 
0573 #if defined(BOOST_INTERPROCESS_WINDOWS)
0574 
0575 inline boost::winapi::DWORD_ __stdcall launch_thread_routine(boost::winapi::LPVOID_ pv)
0576 {
0577    os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
0578    pt->run();
0579    return 0;
0580 }
0581 
0582 #else
0583 
0584 extern "C" void * launch_thread_routine( void * pv );
0585 
0586 inline void * launch_thread_routine( void * pv )
0587 {
0588    os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
0589    pt->run();
0590    return 0;
0591 }
0592 
0593 #endif
0594 
0595 template<class F>
0596 class launch_thread_impl
0597    : public abstract_thread
0598 {
0599    public:
0600    explicit launch_thread_impl( F f )
0601       : f_( f )
0602    {}
0603 
0604    virtual void run() BOOST_OVERRIDE
0605    {  f_();  }
0606 
0607    private:
0608    F f_;
0609 };
0610 
0611 template<class F>
0612 inline int thread_launch( OS_thread_t & pt, F f )
0613 {
0614    os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
0615 
0616    int r = thread_create(&pt, launch_thread_routine, p.get());
0617    if( r == 0 ){
0618       p.release();
0619    }
0620 
0621    return r;
0622 }
0623 
0624 }  //namespace ipcdetail{
0625 }  //namespace interprocess {
0626 }  //namespace boost {
0627 
0628 #include <boost/interprocess/detail/config_end.hpp>
0629 
0630 #endif   //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP