<commit_before>#include "consoleui.h"

using namespace std;

// Presentation layer
//constructor
ConsoleUI::ConsoleUI()
{
}
//runs the whole program
void ConsoleUI::run()
{
    string command;
    bool loop = true;

    bool openFileWorks= _service.load();

    if (openFileWorks)
    {
        while(loop == true)
        {
            cout << "Choose a command:\n";
            cout << endl;
            cout << "register\t- Register a scientist\n";
            cout << "list\t\t- Display the list of scientists\n";
            cout << "search\t\t- Search\n";
            cout << "edit\t\t- Edit scientist\n";
            cout << "delete\t\t- Delete scientist\n";
            cout << "quit\t\t- Exit program\n";
            cout << endl;

            cin >> command;

            // The user can use one lowe case letter for shortcut
            if (command == "list" || command == "List" || command == "l")
            {
                List();
            }
            else if (command == "register" || command == "Register" || command == "r")
            {
                Register();
            }
            else if (command == "search" || command == "Search" || command == "s")
            {
                Search();
            }
            else if (command == "edit" || command == "Edit" || command == "e")
            {
                Edit();
            }
            else if (command == "delete" || command == "Delete" || command == "d")
            {
                Delete();
            }
            else if (command == "quit" || command == "Quit" || command == "q")
            {
                loop = false;
            }
            else
            {
                cout << "Please choose one of the given options!\n";
            }
        }
    }
    else
    {
        cout << "Error with opening file" << endl;
    }
}
//direction for edit scientist
void ConsoleUI::Edit()
{
    // To Do edit functionality
    cout << "Edit registered scientist" << endl;
    int index;
    string change, input;
    //Possible to do list or search
    cout << "Enter the index number of the scientist you want to change: " << endl;
    cin >> index;
    //Write the number of the scientist you want to change
    cout << "Enter what it is that you want to change about the scientist: (name/gender/birth/death) " << endl;
    cin >> change;
    cout << "Enter the new value: " << endl;
    cin >> input;
    //What do you want to change about this scientist
    string message = _service.editScientist(index, change, input);
    cout << message << endl;
}
//direction to delete scientist
void ConsoleUI::Delete()
{
    int index;
    char confirm;

    cout << "Delete registered scientist" << endl;
    cout << endl;
    cout << "Enter scientist number to delete: ";
    cin >> index;

    if (index < _service.getSize())
    {

        cout << "Are you sure you want to delete " << _service.getScientist(index).getName() << "? (y/n): ";
        cin >> confirm;

        if (confirm == 'y' || confirm == 'Y')
        {
            _service.deleteScientist(index);

            cout << endl;
            cout << "Successfully deleted!\n";
            cout << endl;
        }
    }
    else if (index > _service.getSize())
    {
        cout << "Exceeded number of entries!\n";
        cout << endl;
    }
}
//direction to search for scientist
void ConsoleUI::Search()
{
    string searchData;
    //Call the function searchScientists
    cout << "Searching by first letter/s in the name" << endl;
    cout << "Please write the letter/s of the scientist/s that you want to display" << endl;
    cin >> searchData;

    vector<int> foundScientists = _service.searchScientists(searchData);

    cout << endl;

    printFrame();

    for (size_t i = 0; i < foundScientists.size(); i++)
    {
        cout.fill('0');
        cout.width(2);
        cout << right << foundScientists[i] << ". ";
        cout.fill(' ');
        cout.width(25);
        cout << left;
        cout << _service.getScientist(foundScientists[i]).getName();
        cout << "\t";
        cout << _service.getScientist(foundScientists[i]).getGender();
        cout << "\t";
        cout << left << _service.getScientist(foundScientists[i]).getYearOfBirth();
        cout << "\t";
        cout << left << _service.getScientist(foundScientists[i]).getYearOfDeath();
        cout << endl;
    }

    printFrame();

    cout << endl;
}
//direction to sort list
void ConsoleUI::List()
{
    string sort;

    while(sort != "return" && sort!= "Return" && sort != "r")
    {
        cout << endl;
        cout << "Write the option how you want your list sorted\n";
        cout << endl;
        cout << "name\t\t- Sort by name\n";
        cout << "age\t\t- Sort by age\n";
        cout << "birth\t\t- Sort by year of birth\n";
        cout << "death\t\t- Sort by year of death\n";
        cout << "return\t\t- Return to main menu\n";
        cout << endl;

        cin >> sort;
        vector<Scientist> _AllScientist = _service.getScientistVector();
        _AllScientist = SortVector( _AllScientist, sort);

        displayListOfScientist();
    }
}
//direction to register scientist
void ConsoleUI::Register()
{
    string name;
    string gender;
    int yearOfBirth;
    int yearOfDeath;

    cout << "Enter the name of the person:" << endl;
    cin.ignore();
    getline(cin,name);

    cout << "Enter gender (m for male, f for female):" << endl;
    cin >> gender;
    while (gender != "m" && gender != "M" && gender != "f" && gender != "F")
    {
        cout << "Please enter either m or f!\n";
        cin.clear();
        cin >> gender;
    }

    cout << "Enter year of birth:" << endl;
    cin >> yearOfBirth;
    while (cin.fail())
    {
        cout << "ERROR!! Please enter a valid option!\n";
        cin.clear();
        cin.ignore(256, '\n');
        cin >> yearOfBirth;
    }
    while (yearOfBirth > _time.getYearToDay() || yearOfBirth < 0)
    {
        cout << "ERROR!! Please enter a valid year of birth!\n";
        cin.clear();
        cin >> yearOfBirth;
    }

    cout << "Enter year of death or 0 if the person is still alive:" << endl;
    cin >> yearOfDeath;
    while (cin.fail())
    {
        cout << "ERROR!! Please enter a valid option!\n";
        cin.clear();
        cin.ignore(256, '\n');
        cin >> yearOfDeath;
    }
    while (yearOfDeath > _time.getYearToDay() || ((yearOfDeath < yearOfBirth) && yearOfDeath != 0) )
    {
        cout << "ERROR!! Please enter a valid year of death!\n";
        cin.clear();
        cin >> yearOfDeath;
    }

    Scientist scientist(name, gender, yearOfBirth, yearOfDeath);
    _service.addScientist(scientist);

    cout << "Scientist added!" << endl;
    cout << endl;
}
//dislpays list of scientist
void ConsoleUI::displayListOfScientist()
{
    //vector<Scientist> _scientists = _service.getScientistVector();

    printFrame();

    cout << "Nr. Scientist name\t\tGender\tBirth\tDeath\tAge" << endl;
    cout <<"\t\t\t\t\tYear\tYear" << endl;

    for (size_t i = 0; i < _service.getSize() - 1; i++)
    {
        cout.fill('0');
        cout.width(2);
        cout << right << i << ". ";
        cout.fill(' ');
        cout.width(25);
        cout << left;
        cout << _service.getScientist(i).getName();
        cout << "\t";
        cout << _service.getScientist(i).getGender();
        cout << "\t";
        cout << left << _service.getScientist(i).getYearOfBirth();
        cout << "\t";
        cout << left << _service.getScientist(i).getYearOfDeath();
        cout << "\t";
        cout << left << _service.getScientist(i).getAge();
        cout << endl;
    }

    printFrame();
}

void ConsoleUI::printFrame()
{
    cout.fill('=');
    cout.width(63);
    cout << left << "=";
    cout << endl;
    cout.fill(' ');
}

vector<Scientist> ConsoleUI::SortVector(vector<Scientist> _listOfScientist,string sort)
{
   return _service.sortScientists(_listOfScientist, sort);
}
<commit_msg>Small text changes<commit_after>#include "consoleui.h"

using namespace std;

// Presentation layer
//constructor
ConsoleUI::ConsoleUI()
{
}
//runs the whole program
void ConsoleUI::run()
{
    string command;
    bool loop = true;

    bool openFileWorks= _service.load();

    if (openFileWorks)
    {
        while(loop == true)
        {
            cout << "Choose a command:\n";
            cout << endl;
            cout << "register\t- Register a scientist\n";
            cout << "list\t\t- Display the list of scientists\n";
            cout << "search\t\t- Search\n";
            cout << "edit\t\t- Edit scientist\n";
            cout << "delete\t\t- Delete scientist\n";
            cout << "quit\t\t- Exit program\n";
            cout << endl;

            cin >> command;

            // The user can use one lowe case letter for shortcut
            if (command == "list" || command == "List" || command == "l")
            {
                List();
            }
            else if (command == "register" || command == "Register" || command == "r")
            {
                Register();
            }
            else if (command == "search" || command == "Search" || command == "s")
            {
                Search();
            }
            else if (command == "edit" || command == "Edit" || command == "e")
            {
                Edit();
            }
            else if (command == "delete" || command == "Delete" || command == "d")
            {
                Delete();
            }
            else if (command == "quit" || command == "Quit" || command == "q")
            {
                loop = false;
            }
            else
            {
                cout << "Please choose one of the given options!\n";
            }
        }
    }
    else
    {
        cout << "Error with opening file" << endl;
    }
}
//direction for edit scientist
void ConsoleUI::Edit()
{
    // To Do edit functionality
    cout << "Edit registered scientist" << endl;
    int index;
    string change, input;
    //Possible to do list or search
    cout << "Enter the index number of the scientist you want to change: " << endl;
    cin >> index;
    //Write the number of the scientist you want to change
    cout << "Enter what it is that you want to change about the scientist: (name/gender/birth/death) " << endl;
    cin >> change;
    cout << "Enter the new value: " << endl;
    cin >> input;
    //What do you want to change about this scientist
    string message = _service.editScientist(index, change, input);
    cout << message << endl;
}
//direction to delete scientist
void ConsoleUI::Delete()
{
    int index;
    char confirm;

    cout << "Delete registered scientist" << endl;
    cout << endl;
    cout << "Enter scientist number to delete: ";
    cin >> index;

    if (index < _service.getSize())
    {

        cout << "Are you sure you want to delete " << _service.getScientist(index).getName() << "? (y/n): ";
        cin >> confirm;

        if (confirm == 'y' || confirm == 'Y')
        {
            _service.deleteScientist(index);

            cout << endl;
            cout << "Successfully deleted!" << endl;
            cout << endl;
        }
    }
    else if (index > _service.getSize())
    {
        cout << "Index out of range!" << endl;
        cout << endl;
    }
}
//direction to search for scientist
void ConsoleUI::Search()
{
    string searchData;
    //Call the function searchScientists
    cout << "Searching by first letter/s in the name" << endl;
    cout << "Please write the letter/s of the scientist/s that you want to display" << endl;
    cin >> searchData;

    vector<int> foundScientists = _service.searchScientists(searchData);

    cout << endl;

    printFrame();

    for (size_t i = 0; i < foundScientists.size(); i++)
    {
        cout.fill('0');
        cout.width(2);
        cout << right << foundScientists[i] << ". ";
        cout.fill(' ');
        cout.width(25);
        cout << left;
        cout << _service.getScientist(foundScientists[i]).getName();
        cout << "\t";
        cout << _service.getScientist(foundScientists[i]).getGender();
        cout << "\t";
        cout << left << _service.getScientist(foundScientists[i]).getYearOfBirth();
        cout << "\t";
        cout << left << _service.getScientist(foundScientists[i]).getYearOfDeath();
        cout << endl;
    }

    printFrame();

    cout << endl;
}
//direction to sort list
void ConsoleUI::List()
{
    string sort;

    while(sort != "return" && sort!= "Return" && sort != "r")
    {
        cout << endl;
        cout << "Write the option how you want your list sorted\n";
        cout << endl;
        cout << "name\t\t- Sort by name\n";
        cout << "age\t\t- Sort by age\n";
        cout << "birth\t\t- Sort by year of birth\n";
        cout << "death\t\t- Sort by year of death\n";
        cout << "return\t\t- Return to main menu\n";
        cout << endl;

        cin >> sort;
        vector<Scientist> _AllScientist = _service.getScientistVector();
        _AllScientist = SortVector( _AllScientist, sort);

        displayListOfScientist();
    }
}
//direction to register scientist
void ConsoleUI::Register()
{
    string name;
    string gender;
    int yearOfBirth;
    int yearOfDeath;

    cout << "Enter the name of the person:" << endl;
    cin.ignore();
    getline(cin,name);

    cout << "Enter gender (m for male, f for female):" << endl;
    cin >> gender;
    while (gender != "m" && gender != "M" && gender != "f" && gender != "F")
    {
        cout << "Please enter either m or f!\n";
        cin.clear();
        cin >> gender;
    }

    cout << "Enter year of birth:" << endl;
    cin >> yearOfBirth;
    while (cin.fail())
    {
        cout << "ERROR!! Please enter a valid option!\n";
        cin.clear();
        cin.ignore(256, '\n');
        cin >> yearOfBirth;
    }
    while (yearOfBirth > _time.getYearToDay() || yearOfBirth < 0)
    {
        cout << "ERROR!! Please enter a valid year of birth!\n";
        cin.clear();
        cin >> yearOfBirth;
    }

    cout << "Enter year of death or 0 if the person is still alive:" << endl;
    cin >> yearOfDeath;
    while (cin.fail())
    {
        cout << "ERROR!! Please enter a valid option!\n";
        cin.clear();
        cin.ignore(256, '\n');
        cin >> yearOfDeath;
    }
    while (yearOfDeath > _time.getYearToDay() || ((yearOfDeath < yearOfBirth) && yearOfDeath != 0) )
    {
        cout << "ERROR!! Please enter a valid year of death!\n";
        cin.clear();
        cin >> yearOfDeath;
    }

    Scientist scientist(name, gender, yearOfBirth, yearOfDeath);
    _service.addScientist(scientist);

    cout << "Scientist added!" << endl;
    cout << endl;
}
//dislpays list of scientist
void ConsoleUI::displayListOfScientist()
{
    //vector<Scientist> _scientists = _service.getScientistVector();

    printFrame();

    cout << "Nr. Scientist name\t\tGender\tBirth\tDeath\tAge" << endl;
    cout <<"\t\t\t\t\tYear\tYear" << endl;

    for (size_t i = 0; i < _service.getSize() - 1; i++)
    {
        cout.fill('0');
        cout.width(2);
        cout << right << i << ". ";
        cout.fill(' ');
        cout.width(25);
        cout << left;
        cout << _service.getScientist(i).getName();
        cout << "\t";
        cout << _service.getScientist(i).getGender();
        cout << "\t";
        cout << left << _service.getScientist(i).getYearOfBirth();
        cout << "\t";
        cout << left << _service.getScientist(i).getYearOfDeath();
        cout << "\t";
        cout << left << _service.getScientist(i).getAge();
        cout << endl;
    }

    printFrame();
}

void ConsoleUI::printFrame()
{
    cout.fill('=');
    cout.width(63);
    cout << left << "=";
    cout << endl;
    cout.fill(' ');
}

vector<Scientist> ConsoleUI::SortVector(vector<Scientist> _listOfScientist,string sort)
{
   return _service.sortScientists(_listOfScientist, sort);
}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_THREADLIB_HH__
#define __RAPICORN_THREADLIB_HH__

#include <condition_variable>

namespace Rapicorn {
namespace Lib {

#define RAPICORN_CACHE_LINE_ALIGNMENT   128
#define RAPICORN_MFENCE    __sync_synchronize() ///< Memory Fence - prevent processor (and compiler) from reordering loads/stores (read/write barrier).
#define RAPICORN_SFENCE    RAPICORN_X86SFENCE   ///< Store Fence - prevent processor (and compiler) from reordering stores (write barrier).
#define RAPICORN_LFENCE    RAPICORN_X86LFENCE   ///< Load Fence - prevent processor (and compiler) from reordering loads (read barrier).
#define RAPICORN_CFENCE    __asm__ __volatile__ ("" ::: "memory") ///< Compiler Fence, prevent compiler from reordering non-volatiles loads/stores.
#define RAPICORN_X86LFENCE __asm__ __volatile__ ("lfence" ::: "memory") ///< X86 lfence - prevent processor from reordering loads (read barrier).
#define RAPICORN_X86SFENCE __asm__ __volatile__ ("sfence" ::: "memory") ///< X86 sfence - prevent processor from reordering stores (write barrier).

template<typename T> T    atomic_load  (T volatile *p)      { RAPICORN_CFENCE; T t = *p; RAPICORN_LFENCE; return t; }
template<typename T> void atomic_store (T volatile *p, T i) { RAPICORN_SFENCE; *p = i;  RAPICORN_CFENCE; }

template<typename T>
class Atomic {
  T volatile v;
  /*ctor*/  Atomic    () = delete;
  /*ctor*/  Atomic    (T&&) = delete;
protected:
  constexpr Atomic    (T i) : v (i) {}
  Atomic<T>& operator=(Atomic<T> &o) { store (o.load()); return *this; }
  Atomic<T> volatile& operator=(Atomic<T> &o) volatile { store (o.load()); return *this; }
public:
  T         load      () const volatile { return atomic_load (&v); }
  void      store     (T i)    volatile { atomic_store (&v, i); }
  bool      cas  (T o, T n)    volatile { return __sync_bool_compare_and_swap (&v, o, n); }
  T         operator+=(T i)    volatile { return __sync_add_and_fetch (&v, i); }
  T         operator-=(T i)    volatile { return __sync_sub_and_fetch (&v, i); }
  T         operator&=(T i)    volatile { return __sync_and_and_fetch (&v, i); }
  T         operator^=(T i)    volatile { return __sync_xor_and_fetch (&v, i); }
  T         operator|=(T i)    volatile { return __sync_or_and_fetch  (&v, i); }
  T         operator++()       volatile { return __sync_add_and_fetch (&v, 1); }
  T         operator++(int)    volatile { return __sync_fetch_and_add (&v, 1); }
  T         operator--()       volatile { return __sync_sub_and_fetch (&v, 1); }
  T         operator--(int)    volatile { return __sync_fetch_and_sub (&v, 1); }
  void      operator= (T i)    volatile { store (i); }
  operator  T         () const volatile { return load(); }
};

// == Once Scope ==
void once_list_enter  ();
bool once_list_bounce (volatile void *ptr);
bool once_list_leave  (volatile void *ptr);

class OnceScope {
  /*ctor*/       OnceScope (const OnceScope&) = delete;
  OnceScope&     operator= (const OnceScope&) = delete;
  volatile char *volatile flagp;
  bool           entered_once;
public:
  OnceScope (volatile char *volatile p) : flagp (p), entered_once (false) {}
  inline bool
  operator() ()
  {
    if (RAPICORN_LIKELY (*flagp != 0))
      return false;
    if (entered_once > 0)       // second or later invocation from for()
      {
        const bool is_first_initialization = __sync_bool_compare_and_swap (flagp, 0, 1);
        const bool found_and_removed = once_list_leave (flagp);
        if (!is_first_initialization || !found_and_removed)
          printerr ("__once: %s: assertion failed during leave: %d %d", __func__, is_first_initialization, found_and_removed);
      }
    entered_once = 1;           // mark first invocation
    once_list_enter();
    const bool initialized = atomic_load (flagp) != 0;
    const bool needs_init = once_list_bounce (initialized ? NULL : flagp);
    return needs_init;
  }
};

#define RAPICORN_ASECTION(bytes)    __attribute__ ((section (".data.aligned" #bytes), aligned (bytes)))
#define RAPICORN_DO_ONCE_COUNTER    ({ static volatile char RAPICORN_ASECTION (1) __rapicorn_oncebyte_ = 0; &__rapicorn_oncebyte_; })
#define RAPICORN_DO_ONCE   for (Rapicorn::Lib::OnceScope __rapicorn_oncescope_ (RAPICORN_DO_ONCE_COUNTER); __rapicorn_oncescope_(); )

} // Lib
} // Rapicorn

#endif // __RAPICORN_THREADLIB_HH__
<commit_msg>RCORE: document Lib namespace as internal<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_THREADLIB_HH__
#define __RAPICORN_THREADLIB_HH__

#include <condition_variable>

namespace Rapicorn {
namespace Lib { // Namespace for implementation internals

#define RAPICORN_CACHE_LINE_ALIGNMENT   128
#define RAPICORN_MFENCE    __sync_synchronize() ///< Memory Fence - prevent processor (and compiler) from reordering loads/stores (read/write barrier).
#define RAPICORN_SFENCE    RAPICORN_X86SFENCE   ///< Store Fence - prevent processor (and compiler) from reordering stores (write barrier).
#define RAPICORN_LFENCE    RAPICORN_X86LFENCE   ///< Load Fence - prevent processor (and compiler) from reordering loads (read barrier).
#define RAPICORN_CFENCE    __asm__ __volatile__ ("" ::: "memory") ///< Compiler Fence, prevent compiler from reordering non-volatiles loads/stores.
#define RAPICORN_X86LFENCE __asm__ __volatile__ ("lfence" ::: "memory") ///< X86 lfence - prevent processor from reordering loads (read barrier).
#define RAPICORN_X86SFENCE __asm__ __volatile__ ("sfence" ::: "memory") ///< X86 sfence - prevent processor from reordering stores (write barrier).

template<typename T> T    atomic_load  (T volatile *p)      { RAPICORN_CFENCE; T t = *p; RAPICORN_LFENCE; return t; }
template<typename T> void atomic_store (T volatile *p, T i) { RAPICORN_SFENCE; *p = i;  RAPICORN_CFENCE; }

template<typename T>
class Atomic {
  T volatile v;
  /*ctor*/  Atomic    () = delete;
  /*ctor*/  Atomic    (T&&) = delete;
protected:
  constexpr Atomic    (T i) : v (i) {}
  Atomic<T>& operator=(Atomic<T> &o) { store (o.load()); return *this; }
  Atomic<T> volatile& operator=(Atomic<T> &o) volatile { store (o.load()); return *this; }
public:
  T         load      () const volatile { return atomic_load (&v); }
  void      store     (T i)    volatile { atomic_store (&v, i); }
  bool      cas  (T o, T n)    volatile { return __sync_bool_compare_and_swap (&v, o, n); }
  T         operator+=(T i)    volatile { return __sync_add_and_fetch (&v, i); }
  T         operator-=(T i)    volatile { return __sync_sub_and_fetch (&v, i); }
  T         operator&=(T i)    volatile { return __sync_and_and_fetch (&v, i); }
  T         operator^=(T i)    volatile { return __sync_xor_and_fetch (&v, i); }
  T         operator|=(T i)    volatile { return __sync_or_and_fetch  (&v, i); }
  T         operator++()       volatile { return __sync_add_and_fetch (&v, 1); }
  T         operator++(int)    volatile { return __sync_fetch_and_add (&v, 1); }
  T         operator--()       volatile { return __sync_sub_and_fetch (&v, 1); }
  T         operator--(int)    volatile { return __sync_fetch_and_sub (&v, 1); }
  void      operator= (T i)    volatile { store (i); }
  operator  T         () const volatile { return load(); }
};

// == Once Scope ==
void once_list_enter  ();
bool once_list_bounce (volatile void *ptr);
bool once_list_leave  (volatile void *ptr);

class OnceScope {
  /*ctor*/       OnceScope (const OnceScope&) = delete;
  OnceScope&     operator= (const OnceScope&) = delete;
  volatile char *volatile flagp;
  bool           entered_once;
public:
  OnceScope (volatile char *volatile p) : flagp (p), entered_once (false) {}
  inline bool
  operator() ()
  {
    if (RAPICORN_LIKELY (*flagp != 0))
      return false;
    if (entered_once > 0)       // second or later invocation from for()
      {
        const bool is_first_initialization = __sync_bool_compare_and_swap (flagp, 0, 1);
        const bool found_and_removed = once_list_leave (flagp);
        if (!is_first_initialization || !found_and_removed)
          printerr ("__once: %s: assertion failed during leave: %d %d", __func__, is_first_initialization, found_and_removed);
      }
    entered_once = 1;           // mark first invocation
    once_list_enter();
    const bool initialized = atomic_load (flagp) != 0;
    const bool needs_init = once_list_bounce (initialized ? NULL : flagp);
    return needs_init;
  }
};

#define RAPICORN_ASECTION(bytes)    __attribute__ ((section (".data.aligned" #bytes), aligned (bytes)))
#define RAPICORN_DO_ONCE_COUNTER    ({ static volatile char RAPICORN_ASECTION (1) __rapicorn_oncebyte_ = 0; &__rapicorn_oncebyte_; })
#define RAPICORN_DO_ONCE   for (Rapicorn::Lib::OnceScope __rapicorn_oncescope_ (RAPICORN_DO_ONCE_COUNTER); __rapicorn_oncescope_(); )

} // Lib
} // Rapicorn

#endif // __RAPICORN_THREADLIB_HH__
<|endoftext|>


<commit_before>#include "callwindow.h"
#include "ui_callwindow.h"

#include "ui_callingwidget.h"

#include "statisticswindow.h"

#include <QCloseEvent>
#include <QHostAddress>
#include <QtEndian>
#include <QTimer>

const uint16_t MAXOPENPORTS = 42;
const uint16_t PORTSPERPARTICIPANT = 4;

CallWindow::CallWindow(QWidget *parent, uint16_t width, uint16_t height, QString name) :
  QMainWindow(parent),
  ui_(new Ui::CallWindow),
  stats_(new StatisticsWindow(this)),
  conference_(this),
  callNeg_(),
  media_(stats_),
  timer_(new QTimer(this)),
  currentResolution_(),
  portsOpen_(0),
  name_(name)
{
  ui_->setupUi(this);

  currentResolution_ = QSize(width, height);

  // GUI updates are handled solely by timer
  timer_->setInterval(10);
  timer_->setSingleShot(false);
  connect(timer_, SIGNAL(timeout()), this, SLOT(update()));
  connect(timer_, SIGNAL(timeout()), stats_, SLOT(update()));
  timer_->start();

  connect(ui_->stats, SIGNAL(clicked()), this, SLOT(openStatistics()));
}

CallWindow::~CallWindow()
{
  timer_->stop();
  delete timer_;
  stats_->close();
  delete stats_;
  delete ui_;

  media_.uninit();
}

void CallWindow::startStream()
{
  Ui::CallerWidget *ui_widget = new Ui::CallerWidget;
  QWidget* holderWidget = new QWidget;
  ui_widget->setupUi(holderWidget);
  connect(ui_widget->AcceptButton, SIGNAL(clicked()), this, SLOT(acceptCall()));
  connect(ui_widget->DeclineButton, SIGNAL(clicked()), this, SLOT(rejectCall()));

  callNeg_.init(name_);

  QObject::connect(&callNeg_, SIGNAL(incomingINVITE(QString, QString)),
                   this, SLOT(incomingCall(QString, QString)));

  QObject::connect(&callNeg_, SIGNAL(callingOurselves(QString, std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callOurselves(QString, std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                              std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                      std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(ringing(QString)),
                   this, SLOT(ringing(QString)));

  QObject::connect(&callNeg_, SIGNAL(ourCallAccepted(QString, std::shared_ptr<SDPMessageInfo>,
                                                               std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                      std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(ourCallRejected(QString)),
                   this, SLOT(ourCallRejected(QString)));

  QObject::connect(&callNeg_, SIGNAL(callEnded(QString, QString)),
                   this, SLOT(endCall(QString, QString)));

  conferenceMutex_.lock();
  conference_.init(ui_->participantLayout, ui_->participants, ui_widget, holderWidget);
  conferenceMutex_.unlock();

  media_.init();
  media_.startCall(ui_->SelfView, currentResolution_);
}

void CallWindow::addParticipant()
{

  if(portsOpen_ <= MAXOPENPORTS)
  {
    QString ip_str = ui_->ip->toPlainText();

    Contact con;
    con.contactAddress = ip_str;
    con.name = "Unknown";
    if(!name_.isEmpty())
    {
      con.name = name_;
    }
    con.username = "unknown";

    QList<Contact> list;
    list.append(con);

    //start negotiations for this connection

    QList<QString> callIDs = callNeg_.startCall(list);

    for(auto callID : callIDs)
    {
      conferenceMutex_.lock();
      conference_.callingTo(callID, con.name);
      conferenceMutex_.unlock();
    }
  }
}

void CallWindow::createParticipant(QString& callID, std::shared_ptr<SDPMessageInfo> peerInfo,
                                   const std::shared_ptr<SDPMessageInfo> localInfo)
{
  qDebug() << "Adding participant to conference.";

  QHostAddress address;
  address.setAddress(peerInfo->globalAddress);

  in_addr ip;
  ip.S_un.S_addr = qToBigEndian(address.toIPv4Address());

  conferenceMutex_.lock();
  VideoWidget* view = conference_.addVideoStream(callID);
  conferenceMutex_.unlock();

  if(view == NULL)
  {
    qWarning() << "WARNING: NULL widget got from";
    return;
  }

  // TODO: have these be arrays and send video to all of them in case SDP describes it so
  uint16_t sendAudioPort = 0;
  uint16_t recvAudioPort = 0;
  uint16_t sendVideoPort = 0;
  uint16_t recvVideoPort = 0;

  for(auto media : localInfo->media)
  {
    if(media.type == "audio" && recvAudioPort == 0)
    {
      recvAudioPort = media.port;
    }
    else if(media.type == "video" && recvVideoPort == 0)
    {
      recvVideoPort = media.port;
    }
  }

  for(auto media : peerInfo->media)
  {
    if(media.type == "audio" && sendAudioPort == 0)
    {
      sendAudioPort = media.port;
    }
    else if(media.type == "video" && sendVideoPort == 0)
    {
      sendVideoPort = media.port;
    }
  }

  // TODO send all the media if more than one are specified and if required to more than one participant.
  if(sendAudioPort == 0 || recvAudioPort == 0 || sendVideoPort == 0 || recvVideoPort == 0)
  {
    qWarning() << "WARNING: All media ports were not found in given SDP. SendAudio:" << sendAudioPort
               << "recvAudio:" << recvAudioPort << "SendVideo:" << sendVideoPort << "RecvVideo:" << recvVideoPort;
    return;
  }

  if(stats_)
    stats_->addParticipant(peerInfo->globalAddress,
                           QString::number(sendAudioPort),
                           QString::number(sendVideoPort));

  qDebug() << "Sending mediastreams to:" << peerInfo->globalAddress << "audioPort:" << sendAudioPort
           << "VideoPort:" << sendVideoPort;
  media_.addParticipant(callID, ip, sendAudioPort, recvAudioPort, sendVideoPort, recvVideoPort, view);
}

void CallWindow::openStatistics()
{
  stats_->show();
}

void CallWindow::micState()
{
  bool state = media_.toggleMic();

  if(state)
  {
    ui_->mic->setText("Turn mic off");
  }
  else
  {
    ui_->mic->setText("Turn mic on");
  }
}

void CallWindow::cameraState()
{
  bool state = media_.toggleCamera();
  if(state)
  {
    ui_->camera->setText("Turn camera off");
  }
  else
  {
    ui_->camera->setText("Turn camera on");
  }
}

void CallWindow::closeEvent(QCloseEvent *event)
{
  callNeg_.endAllCalls();

  callNeg_.uninit();

  media_.uninit();

  stats_->hide();
  stats_->finished(0);

  conferenceMutex_.lock();
  conference_.close();
  conferenceMutex_.unlock();

  QMainWindow::closeEvent(event);
}

void CallWindow::incomingCall(QString callID, QString caller)
{
  portsOpen_ +=PORTSPERPARTICIPANT;

  if(portsOpen_ > MAXOPENPORTS)
  {
    qWarning() << "WARNING: Ran out of ports:" << portsOpen_ << "/" << MAXOPENPORTS;
    rejectCall(); // TODO: send a not possible message instead of reject.
    return;
  }

  conferenceMutex_.lock();
  conference_.incomingCall(callID, caller);
  conferenceMutex_.unlock();
}

void CallWindow::callOurselves(QString callID, std::shared_ptr<SDPMessageInfo> info)
{
  portsOpen_ +=PORTSPERPARTICIPANT;

  if(portsOpen_ <= MAXOPENPORTS)
  {
    qDebug() << "Calling ourselves, how boring.";
    createParticipant(callID, info, info);
  }
}

void CallWindow::acceptCall()
{
  qDebug() << "We accepted";
  conferenceMutex_.lock();
  QString callID = conference_.acceptNewest();
  conferenceMutex_.unlock();
  callNeg_.acceptCall(callID);
}

void CallWindow::rejectCall()
{
  qDebug() << "We rejected";
  conferenceMutex_.lock();
  QString callID = conference_.rejectNewest();
  conferenceMutex_.unlock();
  callNeg_.rejectCall(callID);
}

void CallWindow::ringing(QString callID)
{
  qDebug() << "call is ringing. TODO: display it to user";
}

void CallWindow::ourCallRejected(QString callID)
{
  qDebug() << "Our Call was rejected. TODO: display it to user";
  conferenceMutex_.lock();
  conference_.removeCaller(callID);
  conferenceMutex_.unlock();
}

void CallWindow::callNegotiated(QString callID, std::shared_ptr<SDPMessageInfo> peerInfo,
                                std::shared_ptr<SDPMessageInfo> localInfo)
{
  qDebug() << "Our call has been accepted.";

  qDebug() << "Sending media to IP:" << peerInfo->globalAddress
           << "to port:" << peerInfo->media.first().port;

  // TODO check the SDP info and do ports and rtp numbers properly
  createParticipant(callID, peerInfo, localInfo);
}

void CallWindow::endCall(QString callID, QString ip)
{
  qDebug() << "Received the end of call message";

  media_.endCall(callID); // must be ended first because of the view.

  conferenceMutex_.lock();
  conference_.removeCaller(callID);
  conferenceMutex_.unlock();

  stats_->removeParticipant(ip);
}
<commit_msg>Removed unnecessary uninit of media.<commit_after>#include "callwindow.h"
#include "ui_callwindow.h"

#include "ui_callingwidget.h"

#include "statisticswindow.h"

#include <QCloseEvent>
#include <QHostAddress>
#include <QtEndian>
#include <QTimer>

const uint16_t MAXOPENPORTS = 42;
const uint16_t PORTSPERPARTICIPANT = 4;

CallWindow::CallWindow(QWidget *parent, uint16_t width, uint16_t height, QString name) :
  QMainWindow(parent),
  ui_(new Ui::CallWindow),
  stats_(new StatisticsWindow(this)),
  conference_(this),
  callNeg_(),
  media_(stats_),
  timer_(new QTimer(this)),
  currentResolution_(),
  portsOpen_(0),
  name_(name)
{
  ui_->setupUi(this);

  currentResolution_ = QSize(width, height);

  // GUI updates are handled solely by timer
  timer_->setInterval(10);
  timer_->setSingleShot(false);
  connect(timer_, SIGNAL(timeout()), this, SLOT(update()));
  connect(timer_, SIGNAL(timeout()), stats_, SLOT(update()));
  timer_->start();

  connect(ui_->stats, SIGNAL(clicked()), this, SLOT(openStatistics()));
}

CallWindow::~CallWindow()
{
  timer_->stop();
  delete timer_;
  stats_->close();
  delete stats_;
  delete ui_;
}

void CallWindow::startStream()
{
  Ui::CallerWidget *ui_widget = new Ui::CallerWidget;
  QWidget* holderWidget = new QWidget;
  ui_widget->setupUi(holderWidget);
  connect(ui_widget->AcceptButton, SIGNAL(clicked()), this, SLOT(acceptCall()));
  connect(ui_widget->DeclineButton, SIGNAL(clicked()), this, SLOT(rejectCall()));

  callNeg_.init(name_);

  QObject::connect(&callNeg_, SIGNAL(incomingINVITE(QString, QString)),
                   this, SLOT(incomingCall(QString, QString)));

  QObject::connect(&callNeg_, SIGNAL(callingOurselves(QString, std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callOurselves(QString, std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                              std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                      std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(ringing(QString)),
                   this, SLOT(ringing(QString)));

  QObject::connect(&callNeg_, SIGNAL(ourCallAccepted(QString, std::shared_ptr<SDPMessageInfo>,
                                                               std::shared_ptr<SDPMessageInfo>)),
                   this, SLOT(callNegotiated(QString, std::shared_ptr<SDPMessageInfo>,
                                                      std::shared_ptr<SDPMessageInfo>)));

  QObject::connect(&callNeg_, SIGNAL(ourCallRejected(QString)),
                   this, SLOT(ourCallRejected(QString)));

  QObject::connect(&callNeg_, SIGNAL(callEnded(QString, QString)),
                   this, SLOT(endCall(QString, QString)));

  conferenceMutex_.lock();
  conference_.init(ui_->participantLayout, ui_->participants, ui_widget, holderWidget);
  conferenceMutex_.unlock();

  media_.init();
  media_.startCall(ui_->SelfView, currentResolution_);
}

void CallWindow::addParticipant()
{

  if(portsOpen_ <= MAXOPENPORTS)
  {
    QString ip_str = ui_->ip->toPlainText();

    Contact con;
    con.contactAddress = ip_str;
    con.name = "Unknown";
    if(!name_.isEmpty())
    {
      con.name = name_;
    }
    con.username = "unknown";

    QList<Contact> list;
    list.append(con);

    //start negotiations for this connection

    QList<QString> callIDs = callNeg_.startCall(list);

    for(auto callID : callIDs)
    {
      conferenceMutex_.lock();
      conference_.callingTo(callID, con.name);
      conferenceMutex_.unlock();
    }
  }
}

void CallWindow::createParticipant(QString& callID, std::shared_ptr<SDPMessageInfo> peerInfo,
                                   const std::shared_ptr<SDPMessageInfo> localInfo)
{
  qDebug() << "Adding participant to conference.";

  QHostAddress address;
  address.setAddress(peerInfo->globalAddress);

  in_addr ip;
  ip.S_un.S_addr = qToBigEndian(address.toIPv4Address());

  conferenceMutex_.lock();
  VideoWidget* view = conference_.addVideoStream(callID);
  conferenceMutex_.unlock();

  if(view == NULL)
  {
    qWarning() << "WARNING: NULL widget got from";
    return;
  }

  // TODO: have these be arrays and send video to all of them in case SDP describes it so
  uint16_t sendAudioPort = 0;
  uint16_t recvAudioPort = 0;
  uint16_t sendVideoPort = 0;
  uint16_t recvVideoPort = 0;

  for(auto media : localInfo->media)
  {
    if(media.type == "audio" && recvAudioPort == 0)
    {
      recvAudioPort = media.port;
    }
    else if(media.type == "video" && recvVideoPort == 0)
    {
      recvVideoPort = media.port;
    }
  }

  for(auto media : peerInfo->media)
  {
    if(media.type == "audio" && sendAudioPort == 0)
    {
      sendAudioPort = media.port;
    }
    else if(media.type == "video" && sendVideoPort == 0)
    {
      sendVideoPort = media.port;
    }
  }

  // TODO send all the media if more than one are specified and if required to more than one participant.
  if(sendAudioPort == 0 || recvAudioPort == 0 || sendVideoPort == 0 || recvVideoPort == 0)
  {
    qWarning() << "WARNING: All media ports were not found in given SDP. SendAudio:" << sendAudioPort
               << "recvAudio:" << recvAudioPort << "SendVideo:" << sendVideoPort << "RecvVideo:" << recvVideoPort;
    return;
  }

  if(stats_)
    stats_->addParticipant(peerInfo->globalAddress,
                           QString::number(sendAudioPort),
                           QString::number(sendVideoPort));

  qDebug() << "Sending mediastreams to:" << peerInfo->globalAddress << "audioPort:" << sendAudioPort
           << "VideoPort:" << sendVideoPort;
  media_.addParticipant(callID, ip, sendAudioPort, recvAudioPort, sendVideoPort, recvVideoPort, view);
}

void CallWindow::openStatistics()
{
  stats_->show();
}

void CallWindow::micState()
{
  bool state = media_.toggleMic();

  if(state)
  {
    ui_->mic->setText("Turn mic off");
  }
  else
  {
    ui_->mic->setText("Turn mic on");
  }
}

void CallWindow::cameraState()
{
  bool state = media_.toggleCamera();
  if(state)
  {
    ui_->camera->setText("Turn camera off");
  }
  else
  {
    ui_->camera->setText("Turn camera on");
  }
}

void CallWindow::closeEvent(QCloseEvent *event)
{
  callNeg_.endAllCalls();

  callNeg_.uninit();

  media_.uninit();

  stats_->hide();
  stats_->finished(0);

  conferenceMutex_.lock();
  conference_.close();
  conferenceMutex_.unlock();

  QMainWindow::closeEvent(event);
}

void CallWindow::incomingCall(QString callID, QString caller)
{
  portsOpen_ +=PORTSPERPARTICIPANT;

  if(portsOpen_ > MAXOPENPORTS)
  {
    qWarning() << "WARNING: Ran out of ports:" << portsOpen_ << "/" << MAXOPENPORTS;
    rejectCall(); // TODO: send a not possible message instead of reject.
    return;
  }

  conferenceMutex_.lock();
  conference_.incomingCall(callID, caller);
  conferenceMutex_.unlock();
}

void CallWindow::callOurselves(QString callID, std::shared_ptr<SDPMessageInfo> info)
{
  portsOpen_ +=PORTSPERPARTICIPANT;

  if(portsOpen_ <= MAXOPENPORTS)
  {
    qDebug() << "Calling ourselves, how boring.";
    createParticipant(callID, info, info);
  }
}

void CallWindow::acceptCall()
{
  qDebug() << "We accepted";
  conferenceMutex_.lock();
  QString callID = conference_.acceptNewest();
  conferenceMutex_.unlock();
  callNeg_.acceptCall(callID);
}

void CallWindow::rejectCall()
{
  qDebug() << "We rejected";
  conferenceMutex_.lock();
  QString callID = conference_.rejectNewest();
  conferenceMutex_.unlock();
  callNeg_.rejectCall(callID);
}

void CallWindow::ringing(QString callID)
{
  qDebug() << "call is ringing. TODO: display it to user";
}

void CallWindow::ourCallRejected(QString callID)
{
  qDebug() << "Our Call was rejected. TODO: display it to user";
  conferenceMutex_.lock();
  conference_.removeCaller(callID);
  conferenceMutex_.unlock();
}

void CallWindow::callNegotiated(QString callID, std::shared_ptr<SDPMessageInfo> peerInfo,
                                std::shared_ptr<SDPMessageInfo> localInfo)
{
  qDebug() << "Our call has been accepted.";

  qDebug() << "Sending media to IP:" << peerInfo->globalAddress
           << "to port:" << peerInfo->media.first().port;

  // TODO check the SDP info and do ports and rtp numbers properly
  createParticipant(callID, peerInfo, localInfo);
}

void CallWindow::endCall(QString callID, QString ip)
{
  qDebug() << "Received the end of call message";

  media_.endCall(callID); // must be ended first because of the view.

  conferenceMutex_.lock();
  conference_.removeCaller(callID);
  conferenceMutex_.unlock();

  stats_->removeParticipant(ip);
}
<|endoftext|>


<commit_before>#ifndef CTHREAD_FORWARD_LIST
#define CTHREAD_FORWARD_LIST
#include<condition_variable>
#include<forward_list>
#include<memory>	//allocator
#include<mutex>
#include<utility>	//forward, move_if_noexcept
//#include<atomic>
//#include<condition_variable>
//#include<memory>	//shared_ptr
//#include<mutex>
//#include<shared_mutex>
//#include<utility>	//forward, move, swap

namespace nThread
{
	template<class T,class Alloc=std::allocator<T>>
	class CThread_forward_list	//a thread-safe std::forward_list
	{
	public:
		using allocator_type=Alloc;
		using value_type=T;
	private:
		std::condition_variable insert_;
		std::mutex insertMut_;
		std::forward_list<value_type,allocator_type> fwd_list_;
	public:
		CThread_forward_list()
			:CThread_forward_list{allocator_type()}{}
		explicit CThread_forward_list(const allocator_type &alloc)
			:fwd_list_{alloc}{}
		template<class ... Args>
		void emplace_front(Args &&...args)
		{
			bool notify;
			std::lock_guard<std::mutex> lock{insertMut_};
			notify=fwd_list_.empty();
			fwd_list_.emplace_front(std::forward<decltype(args)>(args)...);
			if(notify)
				insert_.notify_all();
		}
		inline bool empty() const noexcept
		{
			return fwd_list_.empty();
		}
		template<class UnaryPred>
		void remove_if(UnaryPred &&pred)
		{
			std::lock_guard<std::mutex> lock{insertMut_};
			fwd_list_.remove_if(std::forward<decltype(pred)>(pred));
		}
		//if constructor or assignment operator you use here is not noexcept, it may not be exception safety
		value_type wait_and_pop_front()
		{
			std::unique_lock<std::mutex> lock{insertMut_};
			insert_.wait(lock,[this]() noexcept{return !empty();});
			//1. if move constructor is noexcept, it is exception safety
			//2. if move constructor is not noexcept and copy constructor exists, it is exception safety
			//3. if move constructor is not noexcept and copy constructor does not exist, it may not be exception safety
			const auto temp{std::move_if_noexcept(fwd_list_.front())};
			fwd_list_.pop_front();
			lock.unlock();
			return temp;
		}
	};

	//template<class T>
	//class CThread_forward_list
	//{
	//public:
	//	using value_type=T;
	//private:
	//	struct Node
	//	{
	//		value_type data;
	//		std::shared_ptr<Node> next;
	//		template<class shared_ptrFwdRef,class ... Args>
	//		Node(shared_ptrFwdRef &&next_,Args &&...args)
	//			:data{std::forward<decltype(args)>(args)...},next{std::forward<decltype(next_)>(next_)}{}
	//		~Node()
	//		{
	//			while(next.use_count()==1)
	//			{
	//				std::shared_ptr<Node> p{std::move(next->next)};
	//				next.reset();
	//				next=std::move(p);
	//			}
	//		}
	//	};
	//	std::shared_ptr<Node> begin_;
	//	std::condition_variable cv_;
	//	std::shared_mutex remove_mut_;
	//	std::mutex wait_mut_;
	//public:
	//	CThread_forward_list()=default;
	//	CThread_forward_list(const CThread_forward_list &)=delete;
	//	template<class ... Args>
	//	void emplace_front(Args &&...args)
	//	{
	//		const std::shared_ptr<Node> node{std::make_shared<Node>(std::atomic_load_explicit(&begin_,std::memory_order_relaxed),std::forward<decltype(args)>(args)...)};
	//		std::shared_lock<std::shared_mutex> lock{remove_mut_};
	//		while(!std::atomic_compare_exchange_weak_explicit(&begin_,&node->next,node,std::memory_order_release,std::memory_order_relaxed))
	//			;
	//		cv_.notify_one();
	//	}
	//	//1. do not call emplace_not_ts with greater than or equal to 2 threads at same time
	//	//2. do not call CAtomic_stack::pop_front, CAtomic_stack::remove, CAtomic_stack::remove_if or CAtomic_stack::wait_and_pop_front at same time
	//	template<class ... Args>
	//	inline void emplace_not_ts(Args &&...args)
	//	{
	//		begin_=std::make_shared<Node>(begin_,std::forward<decltype(args)>(args)...);
	//	}
	//	inline bool empty() const noexcept
	//	{
	//		return !begin_.operator bool();
	//	}
	//	//if constructor or assignment operator you use here is not noexcept, it may not be exception safety
	//	value_type pop_front()
	//	{
	//		std::shared_ptr<Node> node{std::atomic_load_explicit(&begin_,std::memory_order_relaxed)};
	//		std::shared_lock<std::shared_mutex> lock{remove_mut_};
	//		while(!std::atomic_compare_exchange_weak_explicit(&begin_,&node,node->next,std::memory_order_acquire,std::memory_order_relaxed))
	//			;
	//		return std::move(node->data);
	//	}
	//	inline void remove(const value_type &remove_val)
	//	{
	//		remove_if([&](const auto &val) noexcept{return val==remove_val;});
	//	}
	//	//will block CAtomic_stack::emplace_front, CAtomic_stack::pop_front and CAtomic_stack::wait_and_pop_front
	//	template<class UnaryPred>
	//	void remove_if(const UnaryPred pred)
	//	{
	//		std::lock<std::shared_mutex> lock{remove_mut_};
	//		for(std::shared_ptr<Node> bef{begin_},iter{bef};iter;)
	//			if(pred(iter->data))
	//				if(begin_==iter)
	//				{
	//					iter=iter->next;
	//					begin_=bef=iter;
	//				}
	//				else
	//				{
	//					std::swap(bef->next,iter->next);
	//					iter=bef->next;
	//				}
	//			else
	//			{
	//				bef=iter;
	//				iter=iter->next;
	//			}
	//	}
	//	//1. if constructor or assignment operator you use here is not noexcept, it may not be exception safety
	//	//2. will block wait_and_pop_front
	//	value_type wait_and_pop_front()
	//	{
	//		std::unique_lock<std::mutex> lock{wait_mut_};
	//		cv_.wait(lock,[this]() noexcept{return !empty();});
	//		//1. if move constructor is noexcept, it is exception safety
	//		//2. if move constructor is not noexcept and copy constructor exists, it is exception safety
	//		//3. if move constructor is not noexcept and copy constructor does not exist, it may not be exception safety
	//		const auto temp{pop_front()};
	//		lock.unlock();
	//		return temp;
	//	}
	//	CThread_forward_list& operator=(const CThread_forward_list &)=delete;
	//};
}

#endif<commit_msg>fix emplace_front<commit_after>#ifndef CTHREAD_FORWARD_LIST
#define CTHREAD_FORWARD_LIST
#include<condition_variable>
#include<forward_list>
#include<memory>	//allocator
#include<mutex>
#include<utility>	//forward, move_if_noexcept
//#include<atomic>
//#include<condition_variable>
//#include<memory>	//shared_ptr
//#include<mutex>
//#include<shared_mutex>
//#include<utility>	//forward, move, swap

namespace nThread
{
	template<class T,class Alloc=std::allocator<T>>
	class CThread_forward_list	//a thread-safe std::forward_list
	{
	public:
		using allocator_type=Alloc;
		using value_type=T;
	private:
		std::condition_variable insert_;
		std::mutex insertMut_;
		std::forward_list<value_type,allocator_type> fwd_list_;
	public:
		CThread_forward_list()
			:CThread_forward_list{allocator_type()}{}
		explicit CThread_forward_list(const allocator_type &alloc)
			:fwd_list_{alloc}{}
		template<class ... Args>
		void emplace_front(Args &&...args)
		{
			bool notify;
			std::lock_guard<std::mutex> lock{insertMut_};
			notify=fwd_list_.empty();
			fwd_list_.emplace_front(std::forward<decltype(args)>(args)...);
			if(notify)
				insert_.notify_all();
		}
		inline bool empty() const noexcept
		{
			return fwd_list_.empty();
		}
		template<class UnaryPred>
		void remove_if(UnaryPred &&pred)
		{
			std::lock_guard<std::mutex> lock{insertMut_};
			fwd_list_.remove_if(std::forward<decltype(pred)>(pred));
		}
		//if constructor or assignment operator you use here is not noexcept, it may not be exception safety
		value_type wait_and_pop_front()
		{
			std::unique_lock<std::mutex> lock{insertMut_};
			insert_.wait(lock,[this]() noexcept{return !empty();});
			//1. if move constructor is noexcept, it is exception safety
			//2. if move constructor is not noexcept and copy constructor exists, it is exception safety
			//3. if move constructor is not noexcept and copy constructor does not exist, it may not be exception safety
			const auto temp{std::move_if_noexcept(fwd_list_.front())};
			fwd_list_.pop_front();
			lock.unlock();
			return temp;
		}
	};

	//template<class T>
	//class CThread_forward_list
	//{
	//public:
	//	using value_type=T;
	//private:
	//	struct Node
	//	{
	//		value_type data;
	//		std::shared_ptr<Node> next;
	//		template<class shared_ptrFwdRef,class ... Args>
	//		Node(shared_ptrFwdRef &&next_,Args &&...args)
	//			:data{std::forward<decltype(args)>(args)...},next{std::forward<decltype(next_)>(next_)}{}
	//		~Node()
	//		{
	//			while(next.use_count()==1)
	//			{
	//				std::shared_ptr<Node> p{std::move(next->next)};
	//				next.reset();
	//				next=std::move(p);
	//			}
	//		}
	//	};
	//	std::shared_ptr<Node> begin_;
	//	std::condition_variable cv_;
	//	std::shared_mutex remove_mut_;
	//	std::mutex wait_mut_;
	//public:
	//	CThread_forward_list()=default;
	//	CThread_forward_list(const CThread_forward_list &)=delete;
	//	template<class ... Args>
	//	void emplace_front(Args &&...args)
	//	{
	//		const std::shared_ptr<Node> node{std::make_shared<Node>(std::atomic_load_explicit(&begin_,std::memory_order_relaxed),std::forward<decltype(args)>(args)...)};
	//		std::shared_lock<std::shared_mutex> lock{remove_mut_};
	//		while(!std::atomic_compare_exchange_weak_explicit(&begin_,&node->next,node,std::memory_order_release,std::memory_order_relaxed))
	//			;
	//		std::lock_guard<std::mutex> lock{wait_mut_};
	//		cv_.notify_one();
	//	}
	//	//1. do not call emplace_not_ts with greater than or equal to 2 threads at same time
	//	//2. do not call CAtomic_stack::pop_front, CAtomic_stack::remove, CAtomic_stack::remove_if or CAtomic_stack::wait_and_pop_front at same time
	//	template<class ... Args>
	//	inline void emplace_not_ts(Args &&...args)
	//	{
	//		begin_=std::make_shared<Node>(begin_,std::forward<decltype(args)>(args)...);
	//	}
	//	inline bool empty() const noexcept
	//	{
	//		return !begin_.operator bool();
	//	}
	//	//if constructor or assignment operator you use here is not noexcept, it may not be exception safety
	//	value_type pop_front()
	//	{
	//		std::shared_ptr<Node> node{std::atomic_load_explicit(&begin_,std::memory_order_relaxed)};
	//		std::shared_lock<std::shared_mutex> lock{remove_mut_};
	//		while(!std::atomic_compare_exchange_weak_explicit(&begin_,&node,node->next,std::memory_order_acquire,std::memory_order_relaxed))
	//			;
	//		return std::move(node->data);
	//	}
	//	inline void remove(const value_type &remove_val)
	//	{
	//		remove_if([&](const auto &val) noexcept{return val==remove_val;});
	//	}
	//	//will block CAtomic_stack::emplace_front, CAtomic_stack::pop_front and CAtomic_stack::wait_and_pop_front
	//	template<class UnaryPred>
	//	void remove_if(const UnaryPred pred)
	//	{
	//		std::lock<std::shared_mutex> lock{remove_mut_};
	//		for(std::shared_ptr<Node> bef{begin_},iter{bef};iter;)
	//			if(pred(iter->data))
	//				if(begin_==iter)
	//				{
	//					iter=iter->next;
	//					begin_=bef=iter;
	//				}
	//				else
	//				{
	//					std::swap(bef->next,iter->next);
	//					iter=bef->next;
	//				}
	//			else
	//			{
	//				bef=iter;
	//				iter=iter->next;
	//			}
	//	}
	//	//1. if constructor or assignment operator you use here is not noexcept, it may not be exception safety
	//	//2. will block wait_and_pop_front
	//	value_type wait_and_pop_front()
	//	{
	//		std::unique_lock<std::mutex> lock{wait_mut_};
	//		cv_.wait(lock,[this]() noexcept{return !empty();});
	//		//1. if move constructor is noexcept, it is exception safety
	//		//2. if move constructor is not noexcept and copy constructor exists, it is exception safety
	//		//3. if move constructor is not noexcept and copy constructor does not exist, it may not be exception safety
	//		const auto temp{pop_front()};
	//		lock.unlock();
	//		return temp;
	//	}
	//	CThread_forward_list& operator=(const CThread_forward_list &)=delete;
	//};
}

#endif<|endoftext|>


<commit_before>#include <exodus/program.h>
programinit()

	function main() {

	var timestarted = time();

	var db1 = COMMAND.a(2);
	var db2 = COMMAND.a(3);

	var silent = OPTIONS.index("S");

	if (not silent)
		logputl("compdbs says 'Hello World!'");

	if (not(db1.connect())) {
		call fsmsg();
		stop(1);
	}

	if (not(db2.connect())) {
		call fsmsg();
		stop(1);
	}

	int nerrors = 0;

	var filenames = COMMAND.field(FM, 4, 9999);
	if (not filenames)
		filenames = db1.listfiles();
	for (var filename : filenames) {

		if (not silent)
			outputl("\n", filename);

		if (filename.substr(1,10) eq "preselect_" or filename.substr(1,14) eq "select_stage2_" or filename eq "dict_all" or filename eq "processes")
			continue;

		var file1;
		if (not file1.open(filename, db1)) {
			call fsmsg();
			stop(1);
		}

		var reccount = file1.reccount();

		var file2;
		if (not file2.open(filename, db2)) {
			call fsmsg();
			stop(1);
		}

		//var keys;
		//if (keys.osread("qwerty")) {
		//	keys.converter("\n", FM);
		//	file1.makelist("", keys);
		//} else
			file1.select("SELECT " ^ filename ^ " (SR)");

		var recn = 0;
		while (file1.readnext(RECORD, ID, MV)) {

			if (esctoexit())
				stop(1);

			recn++;
			if (not silent) {
				output(at(-40), recn, "/", reccount, " ", ID);
				//printl("",RECORD.length());
				if ((recn % 1000) eq 1)
					osflush();
			}

			if (not RECORD) {
				if (not RECORD.read(file1, ID)) {
					errputl(ID, "missing from filename", db1.a(1));
					nerrors++;
					continue;
				}
			}

			var rec2;
			if (not read(rec2, file2, ID)) {
				errputl(ID, " missing from", db2.a(1), filename);
				nerrors++;
				continue;
			}

			if (rec2 ne RECORD and ID.substr(-5,5) != "_XREF") {

				/*
				//revert both records to leading zero 0.1, -0.1 instead of old pickos .1 and -.1;
				RECORD.replacer("([\x1A-\x1F]-?)0\\.", "$1.");
				rec2.replacer("([\x1A-\x1F]-?)0\\.", "$1.");

				//RECORD is db1 and rec2 is db2

				//temp suppress ads field 56
				if (filename eq "ads") {
					RECORD.r(56, rec2.a(56));
					RECORD.swapper(".000", "");
					rec2.swapper(".000", "");
					RECORD.replacer("\\.00([\x1A-\x1F])", "$1");
					rec2.replacer("\\.00([\x1A-\x1F])", "$1");
				} else if (filename eq "brands") {
					RECORD.r(14, rec2.a(14));
					RECORD.r(15, rec2.a(15));
				}

				//if still different, output
				RECORD.cropper();
				rec2.cropper();
				*/
				if (rec2 ne RECORD) {
					nerrors++;
					//errputl(" ", ID, " different.");
					//printl(RECORD);
					//printl(rec2);
					var nfs = dcount(RECORD, FM);
					var nfs2 = dcount(rec2, FM);
					if (nfs2 gt nfs)
						nfs = nfs2;
					for (var fn = 1; fn <= nfs; ++fn) {
						var f1 = RECORD.a(fn);
						var f2 = rec2.a(fn);
						if (f1 ne f2) {
							errputl();
							errputl(filename, " ", ID, " ", fn, "-", f1);
							errputl(filename, " ", ID, " ", fn, "+", f2);
						}
					}
				}
				continue;
			}
		}
	}

	//call stopper("",timestarted,datestarted);

	if (not silent) {
		logputl();
		var seconds = time() - timestarted;
		while (seconds < 0)
			seconds += 86400;
		logputl("Finished in", int(seconds / 60), "minutes and", mod(seconds, 60), "seconds.");
	}

	return nerrors;

}

programexit()
<commit_msg>exclude locks and statistics from dbcomp to allow dbcomp with running database<commit_after>#include <exodus/program.h>
programinit()

	function main() {

	var timestarted = time();

	var db1 = COMMAND.a(2);
	var db2 = COMMAND.a(3);

	var silent = OPTIONS.index("S");

	if (not silent)
		logputl("dbcomp says 'Hello World!'");

	if (not(db1.connect())) {
		call fsmsg();
		stop(1);
	}

	if (not(db2.connect())) {
		call fsmsg();
		stop(1);
	}

	int nerrors = 0;

	var exclude_filenames="dict_all";
	var filenames = COMMAND.field(FM, 4, 9999);
	if (not filenames) {
		filenames = db1.listfiles();
		//TODO get from command line somehow to avoid hardcoding
		exclude_filenames ^= _VM_ "processes" _VM_ "locks" _VM_ "statistics" _VM_ "requestlog";
	}
	for (var filename : filenames) {

		if (not silent)
			outputl("\n", filename);

		if (filename.substr(1,10) eq "preselect_" or filename.substr(1,14) eq "select_stage2_" or locate(filename,exclude_filenames))
			continue;

		var file1;
		if (not file1.open(filename, db1)) {
			call fsmsg();
			stop(1);
		}

		var reccount = file1.reccount();

		var file2;
		if (not file2.open(filename, db2)) {
			call fsmsg();
			stop(1);
		}

		//var keys;
		//if (keys.osread("qwerty")) {
		//	keys.converter("\n", FM);
		//	file1.makelist("", keys);
		//} else
			file1.select("SELECT " ^ filename ^ " (SR)");

		var recn = 0;
		while (file1.readnext(RECORD, ID, MV)) {

			if (esctoexit())
				stop(1);

			recn++;
			if (not silent) {
				output(at(-40), recn, "/", reccount, " ", ID);
				//printl("",RECORD.length());
				if ((recn % 1000) eq 1)
					osflush();
			}

			if (not RECORD) {
				if (not RECORD.read(file1, ID)) {
					errputl(ID, "missing from filename", db1.a(1));
					nerrors++;
					continue;
				}
			}

			var rec2;
			if (not read(rec2, file2, ID)) {
				errputl(ID, " missing from", db2.a(1), filename);
				nerrors++;
				continue;
			}

			if (rec2 ne RECORD and ID.substr(-5,5) != "_XREF") {

				/*
				//revert both records to leading zero 0.1, -0.1 instead of old pickos .1 and -.1;
				RECORD.replacer("([\x1A-\x1F]-?)0\\.", "$1.");
				rec2.replacer("([\x1A-\x1F]-?)0\\.", "$1.");

				//RECORD is db1 and rec2 is db2

				//temp suppress ads field 56
				if (filename eq "ads") {
					RECORD.r(56, rec2.a(56));
					RECORD.swapper(".000", "");
					rec2.swapper(".000", "");
					RECORD.replacer("\\.00([\x1A-\x1F])", "$1");
					rec2.replacer("\\.00([\x1A-\x1F])", "$1");
				} else if (filename eq "brands") {
					RECORD.r(14, rec2.a(14));
					RECORD.r(15, rec2.a(15));
				}

				//if still different, output
				RECORD.cropper();
				rec2.cropper();
				*/
				if (rec2 ne RECORD) {
					nerrors++;
					//errputl(" ", ID, " different.");
					//printl(RECORD);
					//printl(rec2);
					var nfs = dcount(RECORD, FM);
					var nfs2 = dcount(rec2, FM);
					if (nfs2 gt nfs)
						nfs = nfs2;
					for (var fn = 1; fn <= nfs; ++fn) {
						var f1 = RECORD.a(fn);
						var f2 = rec2.a(fn);
						if (f1 ne f2) {
							errputl();
							errputl(filename, " ", ID, " ", fn, "-", f1);
							errputl(filename, " ", ID, " ", fn, "+", f2);
						}
					}
				}
				continue;
			}
		}
	}

	//call stopper("",timestarted,datestarted);

	if (not silent) {
		logputl();
		var seconds = time() - timestarted;
		while (seconds < 0)
			seconds += 86400;
		logputl("Finished in", int(seconds / 60), "minutes and", mod(seconds, 60), "seconds.");
	}

	return nerrors;

}

programexit()
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
using namespace std;
#define N 10000
class Timer
{
public:
	Timer()
		: start_(std::chrono::high_resolution_clock::now())
	{
	}

	~Timer()
	{
		const auto finish = std::chrono::high_resolution_clock::now();
		std::cout << std::chrono::duration_cast<std::chrono::microseconds>(finish - start_).count() << " us" << std::endl;
	}

private:
	const std::chrono::high_resolution_clock::time_point start_;
};

int main() {
	int** firstMatrix = new int*[N];

	for (int i = 0; i < N; ++i) {
		firstMatrix[i] = new int[N];

		for (int j = 0; j < N; ++j) {
			firstMatrix[i][j] = 1;

		}
	}
	int sum = 0;
	{
		Timer t;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				sum += firstMatrix[j][i];
			}
		}
	}
	for (int i = 0; i < N; ++i) {
		delete[] firstMatrix[i];

	}
	delete[] firstMatrix;
	cout << sum << endl;
	return 0;
}
<commit_msg>Update sum_by_columns.cpp<commit_after>#include <chrono>
#include <iostream>
using namespace std;
#define N 10000
class Timer
{
public:
	Timer()
		: start_(std::chrono::high_resolution_clock::now())
	{
	}

	~Timer()
	{
		const auto finish = std::chrono::high_resolution_clock::now();
		std::cout << std::chrono::duration_cast<std::chrono::microseconds>(finish - start_).count() << " us" << std::endl;
	}

private:
	const std::chrono::high_resolution_clock::time_point start_;
};

int main() {
	int** matrix = new int*[N];

	for (int i = 0; i < N; ++i) {
		matrix[i] = new int[N];

		for (int j = 0; j < N; ++j) {
			matrix[i][j] = 1;

		}
	}
	int sum = 0;
	{
		Timer t;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				sum += matrix[j][i];
			}
		}
	}
	for (int i = 0; i < N; ++i) {
		delete[] matrix[i];

	}
	delete[] matrix;
	cout << sum << endl;
	return 0;
}
<|endoftext|>


<commit_before>#include "asocket.h"

// STL
#include <cassert>
#include <cstring>
#include <cstdint>
#include <iostream>

// PDTK
#include "cxxutils/error_helpers.h"
#include "cxxutils/streamcolors.h"
#include "nonposix/getpeercred.h"

#ifndef CMSG_LEN
#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & (size_t) ~ (sizeof(size_t) - 1))
#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr)))
#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
#endif

static_assert(sizeof(uint8_t) == sizeof(char), "size mismatch!");

namespace posix
{
  inline bool getpeercred(fd_t sockfd, proccred_t& cred)
    { return ::getpeercred(sockfd, cred) == posix::success; }
}

AsyncSocket::AsyncSocket(void)
  : AsyncSocket(posix::socket(EDomain::unix, EType::stream, EProtocol::unspec, 0))
{
}

AsyncSocket::AsyncSocket(posix::fd_t socket)
  : m_socket(socket)
{
}

AsyncSocket::~AsyncSocket(void)
{
  if(m_read.is_connected())
    m_read.disconnect();
  if(m_write.is_connected())
    m_write.disconnect();
  if(m_socket != posix::invalid_descriptor)
    posix::close(m_socket);
  m_socket = posix::invalid_descriptor;
  m_accept.detach();
}

bool AsyncSocket::bind(const char *socket_path, int socket_backlog)
{
  if(m_read.is_connected())
    return false;

  assert(std::strlen(socket_path) < sizeof(sockaddr_un::sun_path));
  m_selfaddr = socket_path;
  m_selfaddr = EDomain::unix;
  bool ok = posix::bind(m_socket, m_selfaddr, m_selfaddr.size());
  ok = ok && posix::listen(m_socket, socket_backlog);
  if(ok)
    m_accept = std::thread(&AsyncSocket::async_accept, this);
  return ok;
}

void AsyncSocket::async_accept(void)
{
  posix::sockaddr_t m_peeraddr;
  proccred_t m_peercred;

  socklen_t addrlen;
  m_read.connection = posix::accept(m_socket, m_peeraddr, &addrlen);
  m_write.connection = ::dup(m_read.connection);
  if(m_read.is_connected() &&
     posix::getpeercred(m_read.connection, m_peercred))
  {
    enqueue(connectedToPeer, m_peeraddr, m_peercred);
    m_read .thread = std::thread(&AsyncSocket::async_read , this);
    m_write.thread = std::thread(&AsyncSocket::async_write, this);
  }
}

bool AsyncSocket::connect(const char *socket_path)
{
  if(m_read.is_connected())
    return false;

  assert(std::strlen(socket_path) < sizeof(sockaddr_un::sun_path));
  proccred_t m_peercred;
  posix::sockaddr_t m_peeraddr;
  m_peeraddr = socket_path;
  m_peeraddr = EDomain::unix;

  m_read.connection = m_socket;
  bool ok = m_read.connect(m_peeraddr);
  ok = ok && posix::getpeercred(m_read.connection, m_peercred);
  if(ok)
  {
    m_write.connection = ::dup(m_read.connection);
    enqueue(connectedToPeer, m_peeraddr, m_peercred);
    m_read .thread = std::thread(&AsyncSocket::async_read , this);
    m_write.thread = std::thread(&AsyncSocket::async_write, this);
  }
  else
    m_read.connection = posix::invalid_descriptor;
  return ok;
}

void AsyncSocket::async_read(void)
{
  std::mutex m;
  msghdr msg = {};
  iovec iov = {};

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  for(;;)
  {
    m_read.buffer.allocate(); // allocate 64KB buffer
    std::unique_lock<std::mutex> lk(m);
    m_read.condition.wait(lk, [this] { return m_read.is_connected(); } );

    iov.iov_base = m_read.buffer.data();
    iov.iov_len = m_read.buffer.capacity();
    if(m_read.buffer.expand(posix::recvmsg(m_read.connection, &msg, 0)))
    {
      if(msg.msg_controllen == CMSG_SPACE(sizeof(int)))
      {
        cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
        if(cmsg->cmsg_level == SOL_SOCKET &&
           cmsg->cmsg_type == SCM_RIGHTS &&
           cmsg->cmsg_len == CMSG_LEN(sizeof(int)))
         m_read.fd = *reinterpret_cast<int*>(CMSG_DATA(cmsg));
      }
      else
        m_read.fd = posix::invalid_descriptor;
      enqueue<vqueue&, posix::fd_t>(readFinished, m_read.buffer, m_read.fd);
    }
    else // error
      std::cout << std::flush << std::endl << std::red << "error: " << ::strerror(errno) << std::none << std::endl << std::flush;
  }
}

void AsyncSocket::async_write(void)
{
  std::mutex m;
  msghdr msg = {};
  iovec iov = {};
  char aux_buffer[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(ucred))] = { 0 };

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = aux_buffer;

  for(;;)
  {
    std::unique_lock<std::mutex> lk(m);
    m_write.condition.wait(lk, [this] { return m_write.is_connected() && !m_write.buffer.empty(); } );

    iov.iov_base = m_write.buffer.begin();
    iov.iov_len = m_write.buffer.size();

    msg.msg_controllen = 0;

    if(m_write.fd != posix::invalid_descriptor)
    {
      msg.msg_controllen = CMSG_SPACE(sizeof(int));
      cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
      cmsg->cmsg_level = SOL_SOCKET;
      cmsg->cmsg_type = SCM_RIGHTS;
      cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = m_write.fd;
    }

    int count = posix::sendmsg(m_write.connection, &msg, 0);
    if(count == posix::error_response) // error
      std::cout << std::flush << std::endl << std::red << "error: " << ::strerror(errno) << std::none << std::endl << std::flush;
    else
      enqueue(writeFinished, count);
    m_write.buffer.resize(0);
  }
}

bool AsyncSocket::read(void)
{
  if(!m_read.is_connected())
    return false;
  m_read.condition.notify_one();
  return true;
}

bool AsyncSocket::write(vqueue& buffer, posix::fd_t fd)
{
  if(!m_read.is_connected())
    return false;

  m_write.fd = fd;
  m_write.buffer = buffer; // share buffer memory
  m_write.condition.notify_one();
  return true;
}
<commit_msg>unlike socket file on exit<commit_after>#include "asocket.h"

// STL
#include <cassert>
#include <cstring>
#include <cstdint>
#include <iostream>

// PDTK
#include "cxxutils/error_helpers.h"
#include "cxxutils/streamcolors.h"
#include "nonposix/getpeercred.h"

#ifndef CMSG_LEN
#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & (size_t) ~ (sizeof(size_t) - 1))
#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr)))
#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
#endif

static_assert(sizeof(uint8_t) == sizeof(char), "size mismatch!");

namespace posix
{
  inline bool getpeercred(fd_t sockfd, proccred_t& cred)
    { return ::getpeercred(sockfd, cred) == posix::success; }
}

AsyncSocket::AsyncSocket(void)
{
  const int enable = 1;
  m_socket = posix::socket(EDomain::unix, EType::stream, EProtocol::unspec, 0);
  assert(setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == posix::success);
}

AsyncSocket::AsyncSocket(posix::fd_t socket)
  : m_socket(socket)
{
}

AsyncSocket::~AsyncSocket(void)
{
  if(m_read.is_connected())
    m_read.disconnect();
  if(m_write.is_connected())
    m_write.disconnect();
  if(m_socket != posix::invalid_descriptor)
    posix::close(m_socket);
  m_socket = posix::invalid_descriptor;
  if(m_selfaddr != EDomain::unspec)
    ::unlink(m_selfaddr.sun_path);
  m_accept.detach();

}

bool AsyncSocket::bind(const char *socket_path, int socket_backlog)
{
  if(m_read.is_connected())
    return false;

  assert(std::strlen(socket_path) < sizeof(sockaddr_un::sun_path));
  m_selfaddr = socket_path;
  m_selfaddr = EDomain::unix;
  bool ok = posix::bind(m_socket, m_selfaddr, m_selfaddr.size());
  ok = ok && posix::listen(m_socket, socket_backlog);
  if(ok)
    m_accept = std::thread(&AsyncSocket::async_accept, this);
  return ok;
}

void AsyncSocket::async_accept(void)
{
  posix::sockaddr_t m_peeraddr;
  proccred_t m_peercred;

  socklen_t addrlen;
  m_read.connection = posix::accept(m_socket, m_peeraddr, &addrlen);
  m_write.connection = ::dup(m_read.connection);
  if(m_read.is_connected() &&
     posix::getpeercred(m_read.connection, m_peercred))
  {
    enqueue(connectedToPeer, m_peeraddr, m_peercred);
    m_read .thread = std::thread(&AsyncSocket::async_read , this);
    m_write.thread = std::thread(&AsyncSocket::async_write, this);
  }
}

bool AsyncSocket::connect(const char *socket_path)
{
  if(m_read.is_connected())
    return false;

  assert(std::strlen(socket_path) < sizeof(sockaddr_un::sun_path));
  proccred_t m_peercred;
  posix::sockaddr_t m_peeraddr;
  m_peeraddr = socket_path;
  m_peeraddr = EDomain::unix;
  m_selfaddr = EDomain::unspec;

  m_read.connection = m_socket;
  bool ok = m_read.connect(m_peeraddr);
  ok = ok && posix::getpeercred(m_read.connection, m_peercred);
  if(ok)
  {
    m_write.connection = ::dup(m_read.connection);
    enqueue(connectedToPeer, m_peeraddr, m_peercred);
    m_read .thread = std::thread(&AsyncSocket::async_read , this);
    m_write.thread = std::thread(&AsyncSocket::async_write, this);
  }
  else
    m_read.connection = posix::invalid_descriptor;
  return ok;
}

void AsyncSocket::async_read(void)
{
  std::mutex m;
  msghdr msg = {};
  iovec iov = {};

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  for(;;)
  {
    m_read.buffer.allocate(); // allocate 64KB buffer
    std::unique_lock<std::mutex> lk(m);
    m_read.condition.wait(lk, [this] { return m_read.is_connected(); } );

    iov.iov_base = m_read.buffer.data();
    iov.iov_len = m_read.buffer.capacity();
    if(m_read.buffer.expand(posix::recvmsg(m_read.connection, &msg, 0)))
    {
      if(msg.msg_controllen == CMSG_SPACE(sizeof(int)))
      {
        cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
        if(cmsg->cmsg_level == SOL_SOCKET &&
           cmsg->cmsg_type == SCM_RIGHTS &&
           cmsg->cmsg_len == CMSG_LEN(sizeof(int)))
         m_read.fd = *reinterpret_cast<int*>(CMSG_DATA(cmsg));
      }
      else
        m_read.fd = posix::invalid_descriptor;
      enqueue<vqueue&, posix::fd_t>(readFinished, m_read.buffer, m_read.fd);
    }
    else // error
      std::cout << std::flush << std::endl << std::red << "error: " << ::strerror(errno) << std::none << std::endl << std::flush;
  }
}

void AsyncSocket::async_write(void)
{
  std::mutex m;
  msghdr msg = {};
  iovec iov = {};
  char aux_buffer[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(ucred))] = { 0 };

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = aux_buffer;

  for(;;)
  {
    std::unique_lock<std::mutex> lk(m);
    m_write.condition.wait(lk, [this] { return m_write.is_connected() && !m_write.buffer.empty(); } );

    iov.iov_base = m_write.buffer.begin();
    iov.iov_len = m_write.buffer.size();

    msg.msg_controllen = 0;

    if(m_write.fd != posix::invalid_descriptor)
    {
      msg.msg_controllen = CMSG_SPACE(sizeof(int));
      cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
      cmsg->cmsg_level = SOL_SOCKET;
      cmsg->cmsg_type = SCM_RIGHTS;
      cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = m_write.fd;
    }

    int count = posix::sendmsg(m_write.connection, &msg, 0);
    if(count == posix::error_response) // error
      std::cout << std::flush << std::endl << std::red << "error: " << ::strerror(errno) << std::none << std::endl << std::flush;
    else
      enqueue(writeFinished, count);
    m_write.buffer.resize(0);
  }
}

bool AsyncSocket::read(void)
{
  if(!m_read.is_connected())
    return false;
  m_read.condition.notify_one();
  return true;
}

bool AsyncSocket::write(vqueue& buffer, posix::fd_t fd)
{
  if(!m_read.is_connected())
    return false;

  m_write.fd = fd;
  m_write.buffer = buffer; // share buffer memory
  m_write.condition.notify_one();
  return true;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tbxctl.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2005-03-01 19:18:59 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <ide_pch.hxx>

#pragma hdrstop

#define _BASIDE_POPUPWINDOWTBX
#include <tbxctl.hxx>
#include <svx/svxids.hrc>
#include <iderid.hxx>
#include <tbxctl.hrc>
#include <idetemp.hxx>
#include <sfx2/imagemgr.hxx>
#include <svtools/aeitem.hxx>
#include <vcl/toolbox.hxx>

using namespace ::com::sun::star::uno;

static ::rtl::OUString aSubToolBarResName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/insertcontrolsbar" ) );

SFX_IMPL_TOOLBOX_CONTROL( TbxControls, SfxAllEnumItem )

/*************************************************************************
|*
|* WorkWindow Alignment
|*
\************************************************************************/
/*
IMPL_LINK( PopupWindowTbx, SelectHdl, void*, EMPTYARG )
{
    if ( IsInPopupMode() )
        EndPopupMode();

    aSelectLink.Call( &aTbx.GetToolBox() );

    return 0;
}

PopupWindowTbx::PopupWindowTbx( USHORT nId, WindowAlign eAlign,
                                ResId aRIdWin, ResId aRIdTbx,
                                SfxBindings& rBind ) :
                SfxPopupWindow  ( nId, aRIdWin, rBind ),
                aTbx            ( this, GetBindings(), aRIdTbx )
{
    FreeResource();
    aTbx.Initialize();

    ToolBox& rBox = aTbx.GetToolBox();
    rBox.SetAlign( eAlign );
    if( eAlign == WINDOWALIGN_LEFT )
        SetText( String() );

    Size aSize = aTbx.CalcWindowSizePixel();
    rBox.SetSizePixel( aSize );
    SetOutputSizePixel( aSize );
    aSelectLink = rBox.GetSelectHdl();
    rBox.SetSelectHdl( LINK( this, PopupWindowTbx, SelectHdl ) );
}

SfxPopupWindow* PopupWindowTbx::Clone() const
{
    return new PopupWindowTbx( GetId(), aTbx.GetAlign(),
                        IDEResId( RID_TBXCONTROLS ),
                        IDEResId( RID_TOOLBOX ),
                        (SfxBindings&) GetBindings() );
}

void PopupWindowTbx::PopupModeEnd()
{
    aTbx.GetToolBox().EndSelection();
    SfxPopupWindow::PopupModeEnd();
}

void PopupWindowTbx::Update()
{
    ToolBox *pBox = &aTbx.GetToolBox();
    aTbx.Activate( pBox );
    aTbx.Deactivate( pBox );
}

PopupWindowTbx::~PopupWindowTbx()
{
}
*/
/*************************************************************************
|*
|* Klasse fuer Toolbox
|*
\************************************************************************/

TbxControls::TbxControls( USHORT nSlotId, USHORT nId, ToolBox& rTbx ) :
        SfxToolBoxControl( nSlotId, nId, rTbx )
{
    nLastSlot = USHRT_MAX;

    rTbx.SetItemBits( nId, TIB_DROPDOWN | rTbx.GetItemBits( nId ) );
    rTbx.Invalidate();
}

/*************************************************************************
|*
|* Wenn man ein PopupWindow erzeugen will
|*
\************************************************************************/
SfxPopupWindowType TbxControls::GetPopupWindowType() const
{
    if( nLastSlot == USHRT_MAX )
        return(SFX_POPUPWINDOW_ONCLICK);
    return(SFX_POPUPWINDOW_ONTIMEOUT);
}

IMPL_STATIC_LINK( TbxControls, StateChangedHdl_Impl, StateChangedInfo*, pStateChangedInfo )
{
    try
    {
        if ( pStateChangedInfo )
        {
            Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager( pStateChangedInfo->xLayoutManager );
            if ( xLayoutManager.is() )
            {
                if ( pStateChangedInfo->bDisabled )
                {
                    xLayoutManager->destroyElement( aSubToolBarResName );
                }
                else
                {
                    xLayoutManager->createElement( aSubToolBarResName );
                    xLayoutManager->requestElement( aSubToolBarResName );
                }
            }
        }
    }
    catch ( Exception& )
    {
        // no update
    }

    delete pStateChangedInfo;

    return 0;
}

void TbxControls::StateChanged( USHORT nSID, SfxItemState eState,
  const SfxPoolItem* pState )
{
    if ( nSID == SID_CHOOSE_CONTROLS )
    {
        StateChangedInfo* pStateChangedInfo = new StateChangedInfo;
        pStateChangedInfo->xLayoutManager = getLayoutManager();
        pStateChangedInfo->bDisabled = eState & SFX_ITEM_DISABLED;
        Application::PostUserEvent( STATIC_LINK( 0, TbxControls, StateChangedHdl_Impl ), pStateChangedInfo );
    }

    if( pState )
    {
        SfxAllEnumItem* pItem = PTR_CAST(SfxAllEnumItem, pState);
        if( pItem )
        {
            USHORT nLastEnum = pItem->GetValue();
            USHORT nTemp = 0;
            switch( nLastEnum )
            {
                case SVX_SNAP_PUSHBUTTON:       nTemp = SID_INSERT_PUSHBUTTON; break;
                case SVX_SNAP_CHECKBOX:         nTemp = SID_INSERT_CHECKBOX; break;
                case SVX_SNAP_RADIOBUTTON:      nTemp = SID_INSERT_RADIOBUTTON; break;
                case SVX_SNAP_SPINBUTTON:       nTemp = SID_INSERT_SPINBUTTON; break;
                case SVX_SNAP_FIXEDTEXT:        nTemp = SID_INSERT_FIXEDTEXT; break;
                case SVX_SNAP_GROUPBOX:         nTemp = SID_INSERT_GROUPBOX; break;
                case SVX_SNAP_LISTBOX:          nTemp = SID_INSERT_LISTBOX; break;
                case SVX_SNAP_COMBOBOX:         nTemp = SID_INSERT_COMBOBOX; break;
                case SVX_SNAP_EDIT:             nTemp = SID_INSERT_EDIT; break;
                case SVX_SNAP_HSCROLLBAR:       nTemp = SID_INSERT_HSCROLLBAR; break;
                case SVX_SNAP_VSCROLLBAR:       nTemp = SID_INSERT_VSCROLLBAR; break;
                case SVX_SNAP_PREVIEW:          nTemp = SID_INSERT_PREVIEW; break;
                case SVX_SNAP_URLBUTTON:        nTemp = SID_INSERT_URLBUTTON; break;
                case SVX_SNAP_IMAGECONTROL:     nTemp = SID_INSERT_IMAGECONTROL; break;
                case SVX_SNAP_PROGRESSBAR:      nTemp = SID_INSERT_PROGRESSBAR; break;
                case SVX_SNAP_HFIXEDLINE:       nTemp = SID_INSERT_HFIXEDLINE; break;
                case SVX_SNAP_VFIXEDLINE:       nTemp = SID_INSERT_VFIXEDLINE; break;
                case SVX_SNAP_DATEFIELD:        nTemp = SID_INSERT_DATEFIELD; break;
                case SVX_SNAP_TIMEFIELD:        nTemp = SID_INSERT_TIMEFIELD; break;
                case SVX_SNAP_NUMERICFIELD:     nTemp = SID_INSERT_NUMERICFIELD; break;
                case SVX_SNAP_CURRENCYFIELD:    nTemp = SID_INSERT_CURRENCYFIELD; break;
                case SVX_SNAP_FORMATTEDFIELD:   nTemp = SID_INSERT_FORMATTEDFIELD; break;
                case SVX_SNAP_PATTERNFIELD:     nTemp = SID_INSERT_PATTERNFIELD; break;
                case SVX_SNAP_FILECONTROL:      nTemp = SID_INSERT_FILECONTROL; break;
            }
            if( nTemp )
            {
                rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
                aSlotURL += rtl::OUString::valueOf( sal_Int32( nTemp ));
                Image aImage = GetImage( m_xFrame,
                                         aSlotURL,
                                         hasBigImages(),
                                         GetToolBox().GetDisplayBackground().GetColor().IsDark() );
                ToolBox& rBox = GetToolBox();
                rBox.SetItemImage(GetId(), aImage);
                nLastSlot = nLastEnum;
            }
        }
    }
    SfxToolBoxControl::StateChanged( nSID, eState,pState );
}

void TbxControls::Select( USHORT nModifier )
{
    SfxAllEnumItem aItem( SID_CHOOSE_CONTROLS, nLastSlot );
    SfxViewFrame* pCurFrame = SfxViewFrame::Current();
    DBG_ASSERT( pCurFrame != NULL, "No current view frame!" );
    SfxDispatcher* pDispatcher = pCurFrame ? pCurFrame->GetDispatcher() : NULL;
    if( pDispatcher )
    {
        pDispatcher->Execute( SID_CHOOSE_CONTROLS, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
    }
}

/*************************************************************************
|*
|* Hier wird das Fenster erzeugt
|* Lage der Toolbox mit GetToolBox() abfragbar
|* rItemRect sind die Screen-Koordinaten
|*
\************************************************************************/
SfxPopupWindow* TbxControls::CreatePopupWindow()
{
    if ( GetSlotId() == SID_CHOOSE_CONTROLS )
        createAndPositionSubToolBar( aSubToolBarResName );

/*
    if (GetId() == SID_CHOOSE_CONTROLS)
    {
        PopupWindowTbx *pWin =
            new PopupWindowTbx( GetId(),
                                GetToolBox().IsHorizontal() ?
                                    WINDOWALIGN_LEFT : WINDOWALIGN_TOP,
                                IDEResId( RID_TBXCONTROLS ),
                                IDEResId( RID_TOOLBOX ),
                                GetBindings() );
        pWin->StartPopupMode(&GetToolBox(), TRUE);
        pWin->Update();
        pWin->StartSelection();
        pWin->Show();
        return(pWin);
    }
*/
    return(0);
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.11.60); FILE MERGED 2005/09/05 13:55:49 rt 1.11.60.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tbxctl.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:11:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <ide_pch.hxx>

#pragma hdrstop

#define _BASIDE_POPUPWINDOWTBX
#include <tbxctl.hxx>
#include <svx/svxids.hrc>
#include <iderid.hxx>
#include <tbxctl.hrc>
#include <idetemp.hxx>
#include <sfx2/imagemgr.hxx>
#include <svtools/aeitem.hxx>
#include <vcl/toolbox.hxx>

using namespace ::com::sun::star::uno;

static ::rtl::OUString aSubToolBarResName( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/insertcontrolsbar" ) );

SFX_IMPL_TOOLBOX_CONTROL( TbxControls, SfxAllEnumItem )

/*************************************************************************
|*
|* WorkWindow Alignment
|*
\************************************************************************/
/*
IMPL_LINK( PopupWindowTbx, SelectHdl, void*, EMPTYARG )
{
    if ( IsInPopupMode() )
        EndPopupMode();

    aSelectLink.Call( &aTbx.GetToolBox() );

    return 0;
}

PopupWindowTbx::PopupWindowTbx( USHORT nId, WindowAlign eAlign,
                                ResId aRIdWin, ResId aRIdTbx,
                                SfxBindings& rBind ) :
                SfxPopupWindow  ( nId, aRIdWin, rBind ),
                aTbx            ( this, GetBindings(), aRIdTbx )
{
    FreeResource();
    aTbx.Initialize();

    ToolBox& rBox = aTbx.GetToolBox();
    rBox.SetAlign( eAlign );
    if( eAlign == WINDOWALIGN_LEFT )
        SetText( String() );

    Size aSize = aTbx.CalcWindowSizePixel();
    rBox.SetSizePixel( aSize );
    SetOutputSizePixel( aSize );
    aSelectLink = rBox.GetSelectHdl();
    rBox.SetSelectHdl( LINK( this, PopupWindowTbx, SelectHdl ) );
}

SfxPopupWindow* PopupWindowTbx::Clone() const
{
    return new PopupWindowTbx( GetId(), aTbx.GetAlign(),
                        IDEResId( RID_TBXCONTROLS ),
                        IDEResId( RID_TOOLBOX ),
                        (SfxBindings&) GetBindings() );
}

void PopupWindowTbx::PopupModeEnd()
{
    aTbx.GetToolBox().EndSelection();
    SfxPopupWindow::PopupModeEnd();
}

void PopupWindowTbx::Update()
{
    ToolBox *pBox = &aTbx.GetToolBox();
    aTbx.Activate( pBox );
    aTbx.Deactivate( pBox );
}

PopupWindowTbx::~PopupWindowTbx()
{
}
*/
/*************************************************************************
|*
|* Klasse fuer Toolbox
|*
\************************************************************************/

TbxControls::TbxControls( USHORT nSlotId, USHORT nId, ToolBox& rTbx ) :
        SfxToolBoxControl( nSlotId, nId, rTbx )
{
    nLastSlot = USHRT_MAX;

    rTbx.SetItemBits( nId, TIB_DROPDOWN | rTbx.GetItemBits( nId ) );
    rTbx.Invalidate();
}

/*************************************************************************
|*
|* Wenn man ein PopupWindow erzeugen will
|*
\************************************************************************/
SfxPopupWindowType TbxControls::GetPopupWindowType() const
{
    if( nLastSlot == USHRT_MAX )
        return(SFX_POPUPWINDOW_ONCLICK);
    return(SFX_POPUPWINDOW_ONTIMEOUT);
}

IMPL_STATIC_LINK( TbxControls, StateChangedHdl_Impl, StateChangedInfo*, pStateChangedInfo )
{
    try
    {
        if ( pStateChangedInfo )
        {
            Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager( pStateChangedInfo->xLayoutManager );
            if ( xLayoutManager.is() )
            {
                if ( pStateChangedInfo->bDisabled )
                {
                    xLayoutManager->destroyElement( aSubToolBarResName );
                }
                else
                {
                    xLayoutManager->createElement( aSubToolBarResName );
                    xLayoutManager->requestElement( aSubToolBarResName );
                }
            }
        }
    }
    catch ( Exception& )
    {
        // no update
    }

    delete pStateChangedInfo;

    return 0;
}

void TbxControls::StateChanged( USHORT nSID, SfxItemState eState,
  const SfxPoolItem* pState )
{
    if ( nSID == SID_CHOOSE_CONTROLS )
    {
        StateChangedInfo* pStateChangedInfo = new StateChangedInfo;
        pStateChangedInfo->xLayoutManager = getLayoutManager();
        pStateChangedInfo->bDisabled = eState & SFX_ITEM_DISABLED;
        Application::PostUserEvent( STATIC_LINK( 0, TbxControls, StateChangedHdl_Impl ), pStateChangedInfo );
    }

    if( pState )
    {
        SfxAllEnumItem* pItem = PTR_CAST(SfxAllEnumItem, pState);
        if( pItem )
        {
            USHORT nLastEnum = pItem->GetValue();
            USHORT nTemp = 0;
            switch( nLastEnum )
            {
                case SVX_SNAP_PUSHBUTTON:       nTemp = SID_INSERT_PUSHBUTTON; break;
                case SVX_SNAP_CHECKBOX:         nTemp = SID_INSERT_CHECKBOX; break;
                case SVX_SNAP_RADIOBUTTON:      nTemp = SID_INSERT_RADIOBUTTON; break;
                case SVX_SNAP_SPINBUTTON:       nTemp = SID_INSERT_SPINBUTTON; break;
                case SVX_SNAP_FIXEDTEXT:        nTemp = SID_INSERT_FIXEDTEXT; break;
                case SVX_SNAP_GROUPBOX:         nTemp = SID_INSERT_GROUPBOX; break;
                case SVX_SNAP_LISTBOX:          nTemp = SID_INSERT_LISTBOX; break;
                case SVX_SNAP_COMBOBOX:         nTemp = SID_INSERT_COMBOBOX; break;
                case SVX_SNAP_EDIT:             nTemp = SID_INSERT_EDIT; break;
                case SVX_SNAP_HSCROLLBAR:       nTemp = SID_INSERT_HSCROLLBAR; break;
                case SVX_SNAP_VSCROLLBAR:       nTemp = SID_INSERT_VSCROLLBAR; break;
                case SVX_SNAP_PREVIEW:          nTemp = SID_INSERT_PREVIEW; break;
                case SVX_SNAP_URLBUTTON:        nTemp = SID_INSERT_URLBUTTON; break;
                case SVX_SNAP_IMAGECONTROL:     nTemp = SID_INSERT_IMAGECONTROL; break;
                case SVX_SNAP_PROGRESSBAR:      nTemp = SID_INSERT_PROGRESSBAR; break;
                case SVX_SNAP_HFIXEDLINE:       nTemp = SID_INSERT_HFIXEDLINE; break;
                case SVX_SNAP_VFIXEDLINE:       nTemp = SID_INSERT_VFIXEDLINE; break;
                case SVX_SNAP_DATEFIELD:        nTemp = SID_INSERT_DATEFIELD; break;
                case SVX_SNAP_TIMEFIELD:        nTemp = SID_INSERT_TIMEFIELD; break;
                case SVX_SNAP_NUMERICFIELD:     nTemp = SID_INSERT_NUMERICFIELD; break;
                case SVX_SNAP_CURRENCYFIELD:    nTemp = SID_INSERT_CURRENCYFIELD; break;
                case SVX_SNAP_FORMATTEDFIELD:   nTemp = SID_INSERT_FORMATTEDFIELD; break;
                case SVX_SNAP_PATTERNFIELD:     nTemp = SID_INSERT_PATTERNFIELD; break;
                case SVX_SNAP_FILECONTROL:      nTemp = SID_INSERT_FILECONTROL; break;
            }
            if( nTemp )
            {
                rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
                aSlotURL += rtl::OUString::valueOf( sal_Int32( nTemp ));
                Image aImage = GetImage( m_xFrame,
                                         aSlotURL,
                                         hasBigImages(),
                                         GetToolBox().GetDisplayBackground().GetColor().IsDark() );
                ToolBox& rBox = GetToolBox();
                rBox.SetItemImage(GetId(), aImage);
                nLastSlot = nLastEnum;
            }
        }
    }
    SfxToolBoxControl::StateChanged( nSID, eState,pState );
}

void TbxControls::Select( USHORT nModifier )
{
    SfxAllEnumItem aItem( SID_CHOOSE_CONTROLS, nLastSlot );
    SfxViewFrame* pCurFrame = SfxViewFrame::Current();
    DBG_ASSERT( pCurFrame != NULL, "No current view frame!" );
    SfxDispatcher* pDispatcher = pCurFrame ? pCurFrame->GetDispatcher() : NULL;
    if( pDispatcher )
    {
        pDispatcher->Execute( SID_CHOOSE_CONTROLS, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
    }
}

/*************************************************************************
|*
|* Hier wird das Fenster erzeugt
|* Lage der Toolbox mit GetToolBox() abfragbar
|* rItemRect sind die Screen-Koordinaten
|*
\************************************************************************/
SfxPopupWindow* TbxControls::CreatePopupWindow()
{
    if ( GetSlotId() == SID_CHOOSE_CONTROLS )
        createAndPositionSubToolBar( aSubToolBarResName );

/*
    if (GetId() == SID_CHOOSE_CONTROLS)
    {
        PopupWindowTbx *pWin =
            new PopupWindowTbx( GetId(),
                                GetToolBox().IsHorizontal() ?
                                    WINDOWALIGN_LEFT : WINDOWALIGN_TOP,
                                IDEResId( RID_TBXCONTROLS ),
                                IDEResId( RID_TOOLBOX ),
                                GetBindings() );
        pWin->StartPopupMode(&GetToolBox(), TRUE);
        pWin->Update();
        pWin->StartSelection();
        pWin->Show();
        return(pWin);
    }
*/
    return(0);
}

<|endoftext|>