mardi 29 mars 2016

Linking issues with boost::thread and semaphore extension C++

I am trying to link several binaries to Analysis with an underlying thread pool construct, using the following command:

g++ -std=c++11 -I /usr/lib/x86_64-linux-gnu -lboost_thread  Semaphore.cpp InstrumentReader.cpp InstrumentProcessor.cpp InstrumentManager.cpp Instrument.cpp main.cpp -o Analysis

This yields in the below errors which i am not able to decipher.

lboost_thread  Semaphore.cpp InstrumentReader.cpp InstrumentProcessor.cpp InstrumentManager.cpp Instrument.cpp main.cpp -o Analysis
/tmp/ccPN4zBw.o: In function `Semaphore::Semaphore()':
Semaphore.cpp:(.text+0x1e): undefined reference to `sem_init'
/tmp/ccPN4zBw.o: In function `Semaphore::~Semaphore()':
Semaphore.cpp:(.text+0x38): undefined reference to `sem_destroy'
/tmp/ccPN4zBw.o: In function `Semaphore::GetOrWait()':
Semaphore.cpp:(.text+0x52): undefined reference to `sem_wait'
/tmp/ccPN4zBw.o: In function `Semaphore::operator++()':
Semaphore.cpp:(.text+0x7a): undefined reference to `sem_getvalue'
Semaphore.cpp:(.text+0x86): undefined reference to `sem_post'
/tmp/ccPN4zBw.o: In function `Semaphore::operator--()':
Semaphore.cpp:(.text+0xb2): undefined reference to `sem_getvalue'
Semaphore.cpp:(.text+0xbe): undefined reference to `sem_wait'
/tmp/ccPN4zBw.o: In function `Semaphore::value()':
Semaphore.cpp:(.text+0xea): undefined reference to `sem_getvalue'
/tmp/cc4PBKug.o: In function `__static_initialization_and_destruction_0(int, int)':
InstrumentReader.cpp:(.text+0x26b): undefined reference to `boost::system::generic_category()'
InstrumentReader.cpp:(.text+0x277): undefined reference to `boost::system::generic_category()'
InstrumentReader.cpp:(.text+0x283): undefined reference to `boost::system::system_category()'
/tmp/cczXEYF9.o: In function `__static_initialization_and_destruction_0(int, int)':
InstrumentProcessor.cpp:(.text+0x630): undefined reference to `boost::system::generic_category()'
InstrumentProcessor.cpp:(.text+0x63c): undefined reference to `boost::system::generic_category()'
InstrumentProcessor.cpp:(.text+0x648): undefined reference to `boost::system::system_category()'
/tmp/cczXEYF9.o: In function `boost::thread_exception::thread_exception(int, char const*)':
InstrumentProcessor.cpp:(.text._ZN5boost16thread_exceptionC2EiPKc[_ZN5boost16thread_exceptionC5EiPKc]+0x14): undefined reference to `boost::system::system_category()'
/tmp/cczXEYF9.o: In function `boost::condition_error::condition_error(int, char const*)':
InstrumentProcessor.cpp:(.text._ZN5boost15condition_errorC2EiPKc[_ZN5boost15condition_errorC5EiPKc]+0x14): undefined reference to `boost::system::system_category()'
/tmp/cczXEYF9.o: In function `boost::detail::thread_data_base::thread_data_base()':
InstrumentProcessor.cpp:(.text._ZN5boost6detail16thread_data_baseC2Ev[_ZN5boost6detail16thread_data_baseC5Ev]+0x24): undefined reference to `vtable for boost::detail::thread_data_base'
/tmp/cczXEYF9.o: In function `boost::detail::interruption_checker::interruption_checker(pthread_mutex_t*, pthread_cond_t*)':
InstrumentProcessor.cpp:(.text._ZN5boost6detail20interruption_checkerC2EP15pthread_mutex_tP14pthread_cond_t[_ZN5boost6detail20interruption_checkerC5EP15pthread_mutex_tP14pthread_cond_t]+0x16): undefined reference to `boost::detail::get_current_thread_data()'
/tmp/cczXEYF9.o: In function `boost::thread::start_thread()':
InstrumentProcessor.cpp:(.text._ZN5boost6thread12start_threadEv[_ZN5boost6thread12start_threadEv]+0x15): undefined reference to `boost::thread::start_thread_noexcept()'
/tmp/cczXEYF9.o: In function `boost::thread::~thread()':
InstrumentProcessor.cpp:(.text._ZN5boost6threadD2Ev[_ZN5boost6threadD5Ev]+0x14): undefined reference to `boost::thread::detach()'
/tmp/cczXEYF9.o: In function `boost::thread::get_id() const':
InstrumentProcessor.cpp:(.text._ZNK5boost6thread6get_idEv[_ZNK5boost6thread6get_idEv]+0x18): undefined reference to `boost::thread::native_handle()'
/tmp/cczXEYF9.o: In function `boost::thread::join()':
InstrumentProcessor.cpp:(.text._ZN5boost6thread4joinEv[_ZN5boost6thread4joinEv]+0x6d): undefined reference to `boost::thread::join_noexcept()'
/tmp/cczXEYF9.o: In function `boost::condition_variable::wait(boost::unique_lock<boost::mutex>&)':
InstrumentProcessor.cpp:(.text._ZN5boost18condition_variable4waitERNS_11unique_lockINS_5mutexEEE[_ZN5boost18condition_variable4waitERNS_11unique_lockINS_5mutexEEE]+0x8b): undefined reference to `boost::this_thread::interruption_point()'
/tmp/cczXEYF9.o: In function `boost::shared_mutex::lock_shared()':
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[_ZN5boost12shared_mutex11lock_sharedEv]+0x15): undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[_ZN5boost12shared_mutex11lock_sharedEv]+0x7c): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[_ZN5boost12shared_mutex11lock_sharedEv]+0x9e): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
/tmp/cczXEYF9.o: In function `boost::shared_mutex::lock()':
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex4lockEv[_ZN5boost12shared_mutex4lockEv]+0x15): undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex4lockEv[_ZN5boost12shared_mutex4lockEv]+0x86): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
InstrumentProcessor.cpp:(.text._ZN5boost12shared_mutex4lockEv[_ZN5boost12shared_mutex4lockEv]+0xa8): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
/tmp/cczXEYF9.o: In function `boost::thread_group::join_all()':
InstrumentProcessor.cpp:(.text._ZN5boost12thread_group8join_allEv[_ZN5boost12thread_group8join_allEv]+0x59): undefined reference to `boost::thread::joinable() const'
/tmp/cczXEYF9.o: In function `boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, InstrumentProcessor>, boost::_bi::list1<boost::_bi::value<InstrumentProcessor*> > > >::~thread_data()':
InstrumentProcessor.cpp:(.text._ZN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf0Iv19InstrumentProcessorEENS2_5list1INS2_5valueIPS6_EEEEEEED2Ev[_ZN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf0Iv19InstrumentProcessorEENS2_5list1INS2_5valueIPS6_EEEEEEED5Ev]+0x1f): undefined reference to `boost::detail::thread_data_base::~thread_data_base()'
/tmp/cczXEYF9.o:(.rodata._ZTIN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf0Iv19InstrumentProcessorEENS2_5list1INS2_5valueIPS6_EEEEEEEE[_ZTIN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf0Iv19InstrumentProcessorEENS2_5list1INS2_5valueIPS6_EEEEEEEE]+0x10): undefined reference to `typeinfo for boost::detail::thread_data_base'
/tmp/ccQvaI09.o: In function `__static_initialization_and_destruction_0(int, int)':
InstrumentManager.cpp:(.text+0x23b): undefined reference to `boost::system::generic_category()'
InstrumentManager.cpp:(.text+0x247): undefined reference to `boost::system::generic_category()'
InstrumentManager.cpp:(.text+0x253): undefined reference to `boost::system::system_category()'
/tmp/ccxHiUTc.o: In function `__static_initialization_and_destruction_0(int, int)':
Instrument.cpp:(.text+0x56c): undefined reference to `boost::system::generic_category()'
Instrument.cpp:(.text+0x578): undefined reference to `boost::system::generic_category()'
Instrument.cpp:(.text+0x584): undefined reference to `boost::system::system_category()'
/tmp/cclT6aOm.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x106): undefined reference to `boost::system::generic_category()'
main.cpp:(.text+0x112): undefined reference to `boost::system::generic_category()'
main.cpp:(.text+0x11e): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status

The relevant class details are as below: Semaphore.h:

#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#include <semaphore.h>

class Semaphore

{
  public:
    Semaphore();
    ~Semaphore();
    void GetOrWait();
    //pre-increment
    int operator++ ();
    //pre-decrement
    int operator-- ();
    int value();

  private:
    sem_t semaphore_;

    // Removed copy constructor and copy assignment operator
    Semaphore(const Semaphore &){}
    Semaphore& operator = (const Semaphore &){return *this;}

};

#endif /* SEMAPHORE_H */

Semaphore.cpp:

#include "Semaphore.h"

Semaphore::Semaphore()
{
    sem_init(&semaphore_, 0, 0); // Non-Shared, Initial Value = 0
}


Semaphore::~Semaphore()
{
    sem_destroy(&semaphore_);
}

/* If the semaphore's value is greater than zero, then the decrement proceeds,
 * and the function returns, immediately.
 * If the semaphore currently has the value zero, then the call blocks
 * until it becomes possible to perform the decrement.
 */

void Semaphore::GetOrWait()
{
    sem_wait(&semaphore_);
}

// pre-increment
int Semaphore::operator++ ()
{
    int value = 0;
    sem_getvalue(&semaphore_, &value);
    sem_post(&semaphore_);
    return value;
}

// pre-decrement
int Semaphore::operator--()
{
    int value = 0;
    sem_getvalue(&semaphore_, &value);
    sem_wait(&semaphore_);
    return value;
}

int Semaphore::value()
{
    int value = 0;
    sem_getvalue(&semaphore_, &value);
    return value;
}

InstrumentProcessor.h

#ifndef INSTRUMENTPROCESSOR_H
#define INSTRUMENTPROCESSOR_H

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include "Semaphore.h"
#include "Instrument.h"
#include <queue>
#include <string>
#include <vector>
#include <atomic>


class InstrumentProcessor
{
    public:
    InstrumentProcessor(unsigned int const numThreads);
    ~InstrumentProcessor();
    bool Start();
    bool Stop();
    bool getStop();
    void AddLine(const std::string& LineRead); // Producer

    private:
    void Process(); // Worker Function
    void ProcessLine(std::string& line); // Consumer

    private:
    unsigned int const numThreads_;
    boost::mutex ProcessorMutex_;
    boost::thread_group ProcessorGroup_;
    Semaphore taskCount_;
    std::queue<std::string> Line_;
    std::atomic<bool> stop_;
    std::vector<std::string> elements_;
    std::vector<Instrument> Instruments_;
};

#endif /* INSTRUMENTPROCESSOR_H */

InstrumentProcessor.cpp

#include "InstrumentProcessor.h"

InstrumentProcessor::InstrumentProcessor(unsigned int const numThreads)
: numThreads_(numThreads), stop_(false)
{
    Instruments_.reserve(25);
}

InstrumentProcessor::~InstrumentProcessor()
{

}

bool InstrumentProcessor::Start()
{
    std::cout << "\nParallel Processing Started ...." << std::endl;
    for(unsigned int i=0; i<numThreads_; i++)
    {
        ProcessorGroup_.create_thread(boost::bind(&InstrumentProcessor::Process, this));
    }

    return true;
}

bool InstrumentProcessor::Stop()
{
    stop_ = true;
    ProcessorGroup_.join_all();
    std::cout << "\n Parallel Processing Stopped ...." << std::endl;
    return stop_;
}


void InstrumentProcessor::Process()
{
    while(!stop_)
    {
        --taskCount_;
        std::string currentLine;
        {
            boost::mutex::scoped_lock lock(ProcessorMutex_);
            currentLine = Line_.front();
            Line_.pop();
        }
        ProcessLine(currentLine); 
    }
}

void InstrumentProcessor::AddLine(const std::string& LineRead)
{
    boost::mutex::scoped_lock lock(ProcessorMutex_);
    Line_.push(LineRead);
    ++taskCount_;
}

void InstrumentProcessor::ProcessLine(std::string& line)
{
    boost::algorithm::split(elements_, line, boost::is_any_of("\t "), boost::token_compress_on);
    for(unsigned int i=1; i<elements_.size(); i++)
    {
        if (elements_[i].compare("nan") == 0)
            continue;
        else
        {
            double data = boost::lexical_cast<double>(elements_[i]);
            Instruments_[i-1].CleanData(data);
        }
    }
}

bool InstrumentProcessor::getStop()
{
    return stop_;
}

InstrumentManager.h

#ifndef INSTRUMENTMANAGER_H
#define INSTRUMENTMANAGER_H

#include "InstrumentProcessor.h"
#include "InstrumentReader.h"
#include <string>

class InstrumentManager
{
    public:
    InstrumentManager(std::string& filename);
    ~InstrumentManager();
    bool Start();

    private:
    InstrumentManager(const InstrumentManager& manager);
    InstrumentManager& operator=(const InstrumentManager& manager);

    private:
    std::string filename_;
    InstrumentReader Reader_;
    InstrumentProcessor* Processor_;
};

#endif /* INSTRUMENTMANAGER_H */

InstrumentManager.cpp

#include "InstrumentManager.h"

InstrumentManager::InstrumentManager(std::string& filename)
: filename_(filename), Processor_(new InstrumentProcessor(5)), Reader_(filename_, Processor_)
{

}

InstrumentManager::InstrumentManager(const InstrumentManager& manager)
:filename_(manager.filename_), Processor_(new InstrumentProcessor(5)), Reader_(filename_, manager.Processor_)
{

}

InstrumentManager& InstrumentManager::operator=(const InstrumentManager& manager)
{
    return *this;
}


InstrumentManager::~InstrumentManager()
{
    delete Processor_;
}

bool InstrumentManager::Start()
{
    Reader_.GetLinesFromFile();
    Processor_->Start();
    return true;
}

Instrument.h

#ifndef INSTRUMENT_H
#define INSTRUMENT_H

#include <iostream>
#include <boost/thread/mutex.hpp>
#include <cmath>

class Instrument
{
    public:
    Instrument();
    Instrument(Instrument&& instrument);
    ~Instrument();
    bool PopulateData(double& data);
    bool CleanData(double& data);
    double getMean();
    double getData();
    double getDev();
    bool PrintData();

    private:
    bool getMeanAndStandardDeviation();

        private:
        double data_;
        int N_;
        double Mean_;
        double M2_;
        double stdDev_;
        double InitialValue_;
        bool Init_;
    boost::mutex InstrumentMutex_;  
};

#endif /* INSTRUMENT_H */

Instrument.cpp

#include "Instrument.h"

Instrument::Instrument()
: Init_(false), data_(0.0), Mean_(0.0), stdDev_(0.0), InitialValue_(0.0), N_(0), M2_(0.0)
{

}

Instrument::Instrument(Instrument&& instrument)
: Init_(std::move(instrument.Init_)), data_(std::move(instrument.data_)), 
  Mean_(std::move(instrument.Mean_)), stdDev_(std::move(instrument.stdDev_)),
  InitialValue_(std::move(instrument.InitialValue_)), N_(std::move(instrument.N_)), M2_(std::move(instrument.M2_))
{

}

Instrument::~Instrument()
{

}

bool Instrument::PopulateData(double& data)
{
    data_ = data;
    if(!Init_)
    {
        InitialValue_ = data_;
        Init_ = true;
        std::cout << "The initial value is: " << InitialValue_ << std::endl;
    }
    return true;
}

/* Cleaning Part 2:
* Each data point will be represented as the % change from the initial value. 
* This will then be added by 101 so as to get uniform positive value with the 
* origin of the data shifted to init_origin + 101
*/

bool Instrument::CleanData(double& data)
{

    std::cout << "\nData begin inserted: " << data << std::endl;
    boost::mutex::scoped_lock lock(InstrumentMutex_);
    PopulateData(data);
    data_ = ((data_-InitialValue_)/InitialValue_)*100;
    data_ += 101;
    getMeanAndStandardDeviation();
    return true;
}

// Welford recurrence relation for tick based mean and standard deviation calculation
bool Instrument::getMeanAndStandardDeviation()
{
    ++N_;
    double delta = data_ - Mean_;
    Mean_ += delta/N_;
    M2_ += delta*(data_ - Mean_);

    if(N_ >= 2)
    {
        double variance = M2_/(N_-1);
        stdDev_ = std::sqrt(variance);
    }
    return true;        
}

double Instrument::getData()
{
    boost::mutex::scoped_lock lock(InstrumentMutex_);
    return data_;
}

double Instrument::getMean()
{
    boost::mutex::scoped_lock lock(InstrumentMutex_);
    return Mean_;
}

double Instrument::getDev()
{
    boost::mutex::scoped_lock(InstrumentMutex_);
    return stdDev_;
}

bool Instrument::PrintData()
{
    std::cout << "\nMean: " << Mean_ << "Std Dev: " << stdDev_ << std::endl;
    return true;
}

main.cpp

#include <iostream>
#include <string>
#include "InstrumentManager.h"

int main()
{
    std::string filename = "data_format.txt";
    InstrumentManager mgr(filename);
    mgr.Start();
    return 0;
}

Any help is much appreciated.

Aucun commentaire:

Enregistrer un commentaire