<commit_before>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>
#include <LUtils.h>
#include <LDesktopUtils.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
  generateTipOfTheDay();
  ui->label_version->setText( QString(tr("Version %1")).arg(LDesktopUtils::LuminaDesktopVersion()) );
}

void BootSplash::generateTipOfTheDay(){
  int index = qrand()%46; //Make sure this number matches the length of the case below (max value +1)
  QString tip;
  switch(index){
    case 0:
	tip = tr("This desktop is powered by coffee, coffee, and more coffee."); break;
    case 1:
	tip = tr("Keep up with desktop news!")+"\n\nwww.lumina-desktop.org"; break;
    case 2:
	tip = tr("There is a full handbook of information about the desktop available online.")+"\n\nwww.lumina-desktop.org/handbook"; break;
    case 3:
	tip = tr("Want to change the interface? Everything is customizable in the desktop configuration!"); break;
    case 4:
	tip = tr("Lumina can easily reproduce the interface from most other desktop environments."); break;
    case 5:
	tip = tr("This desktop is generously sponsored by iXsystems")+"\n\nwww.ixsystems.com"; break;
    case 6:
	tip = "\""+tr("I have never been hurt by what I have not said")+"\"\n\n- Calvin Coolidge -"; break;
    case 7:
	tip = "\""+tr("Gotta have more cowbell!")+"\"\n\n- Christopher Walken (SNL) -"; break;
    case 8:
	tip = "\""+tr("Everything has its beauty but not everyone sees it.")+"\"\n\n- Confucius -"; break;
    case 9:
	tip = "\""+tr("Before God we are all equally wise - and equally foolish.")+"\"\n\n- Albert Einstein -"; break;
    case 10:
	tip = "\""+tr("We cannot do everything at once, but we can do something at once.")+"\"\n\n- Calvin Coolidge -"; break;
    case 11:
	tip = "\""+tr("One with the law is a majority.")+"\"\n\n- Calvin Coolidge -"; break;
    case 12:
	tip = "\""+tr("Don't expect to build up the weak by pulling down the strong.")+"\"\n\n- Calvin Coolidge -"; break;
    case 13:
	tip = "\""+tr("You can't know too much, but you can say too much.")+"\"\n\n- Calvin Coolidge -"; break;
    case 14:
	tip = "\""+tr("Duty is not collective; it is personal.")+"\"\n\n- Calvin Coolidge -"; break;
    case 15:
	tip = "\""+tr("Any society that would give up a little liberty to gain a little security will deserve neither and lose both.")+"\"\n\n- Benjamin Franklin -"; break;
    case 16:
	tip = "\""+tr("Never trust a computer you can’t throw out a window.")+"\"\n\n- Steve Wozniak -"; break;
    case 17:
	tip = "\""+tr("Study the past if you would define the future.")+"\"\n\n- Confucius -"; break;
    case 18:
	tip = "\""+tr("The way to get started is to quit talking and begin doing.")+"\"\n\n- Walt Disney -"; break;
    case 19:
	tip = "\""+tr("Ask and it will be given to you; search, and you will find; knock and the door will be opened for you.")+"\"\n\n- Jesus Christ -"; break;
    case 20:
	tip = "\""+tr("Start where you are. Use what you have.  Do what you can.")+"\"\n\n- Arthur Ashe -"; break;
    case 21:
	tip = "\""+tr("A person who never made a mistake never tried anything new.")+"\"\n\n- Albert Einstein -"; break;
    case 22:
	tip = "\""+tr("It does not matter how slowly you go as long as you do not stop.")+"\"\n\n- Confucius -"; break;
    case 23:
	tip = "\""+tr("Do what you can, where you are, with what you have.")+"\"\n\n- Theodore Roosevelt -"; break;
    case 24:
	tip = "\""+tr("Remember no one can make you feel inferior without your consent.")+"\"\n\n- Eleanor Roosevelt -"; break;
    case 25:
	tip = "\""+tr("It’s not the years in your life that count. It’s the life in your years.")+"\"\n\n- Abraham Lincoln -"; break;
    case 26:
	tip = "\""+tr("Either write something worth reading or do something worth writing.")+"\"\n\n- Benjamin Franklin -"; break;
    case 27:
	tip = "\""+tr("The only way to do great work is to love what you do.")+"\"\n\n- Steve Jobs -"; break;
    case 28:
	tip = "\""+tr("Political correctness is tyranny with manners.")+"\"\n\n- Charlton Heston -"; break;
    case 29:
	tip = "\""+tr("Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.")+"\"\n\n- Albert Einstein -"; break;
    case 30:
	tip = "\""+tr("I find that the harder I work, the more luck I seem to have.")+"\"\n\n- Thomas Jefferson -"; break;
    case 31:
	tip = "\""+tr("Do, or do not. There is no 'try'.")+"\"\n\n- Yoda -"; break;
    case 32:
	tip = "\""+tr("A mathematician is a device for turning coffee into theorems.")+"\"\n\n- Paul Erdos -"; break;
    case 33:
	tip = "\""+tr("Good people do not need laws to tell them to act responsibly, while bad people will find a way around the laws.")+"\"\n\n- Plato -"; break;
    case 34:
	tip = "\""+tr("Black holes are where God divided by zero.")+"\"\n\n- Steven Wright -"; break;
    case 35:
	tip = "\""+tr("It's kind of fun to do the impossible.")+"\"\n\n- Walt Disney -"; break;
    case 36:
	tip = "\""+tr("Knowledge speaks, but wisdom listens.")+"\"\n\n- Jimi Hendrix -"; break;
    case 37:
	tip = "\""+tr("A witty saying proves nothing.")+"\"\n\n- Voltaire -"; break;
    case 38:
	tip = "\""+tr("Success usually comes to those who are too busy to be looking for it.")+"\"\n\n- Henry David Thoreau -"; break;
    case 39:
	tip = "\""+tr("Well-timed silence hath more eloquence than speech.")+"\"\n\n- Martin Fraquhar Tupper -"; break;
    case 40:
	tip = "\""+tr("I have never let my schooling interfere with my education.")+"\"\n\n- Mark Twain -"; break;
    case 41:
	tip = "\""+tr("The best way to predict the future is to invent it.")+"\"\n\n- Alan Kay -"; break;
    case 42:
	tip = "\""+tr("Well done is better than well said.")+"\"\n\n- Benjamin Franklin -"; break;
    case 43:
	tip = "\""+tr("Sometimes it is not enough that we do our best; we must do what is required.")+"\"\n\n- Sir Winston Churchill -"; break;
    case 44:
	tip = "\""+tr("The truth is more important than the facts.")+"\"\n\n- Frank Lloyd Wright -"; break;
    case 45:
	tip = "\""+tr("Better to remain silent and be thought a fool than to speak out and remove all doubt.")+"\"\n\n- Abraham Lincoln -"; break;
  }
  ui->label_welcome->setText( tip);
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session …"); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading System Settings …"); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Loading User Preferences …"); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Preparing System Tray …"); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager …"); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting Applications …"); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Preparing Menus …"); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Preparing Workspace …"); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Finalizing …"); per = 90;
    icon = "start-here-lumina";
  }else if(loading.startsWith("app::")){
    txt = QString(tr("Starting App: %1")).arg(loading.section("::",1,50)); per = -1;
  }
  if(per>0){ ui->progressBar->setValue(per); }
  else{ ui->progressBar->setRange(0,0); } //loading indicator
  ui->label_text->setText(txt);
  if(!icon.isEmpty()){ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) ); }
  this->raise();
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}
<commit_msg>Add new options for the Lumina tips: If a lumina-motd file (executable or text) is found within one of the etc directories (/usr/local/etc/lumina-motd on FreeBSD) or as a valid binary on PATH, then that file will be "preferred" for generating the tips rather than the built-in system. This allows system administrators and/or OS-distributors to customize the login messages "at will" for their particular use-case. NOTE: By making the lumina-motd file a blank text file the tips will be disabled.<commit_after>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>
#include <LUtils.h>
#include <LDesktopUtils.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
  generateTipOfTheDay();
  ui->label_version->setText( QString(tr("Version %1")).arg(LDesktopUtils::LuminaDesktopVersion()) );
}

void BootSplash::generateTipOfTheDay(){
  //Try to find a system-defined message of the day for lumina
  QStringList dirs; dirs << LOS::AppPrefix()+"/etc/" << LOS::SysPrefix()+"/etc/" << L_ETCDIR+"/";
  QString sysMOTD = "lumina-motd";
  for(int i=0; i<dirs.length(); i++){
    if(QFile::exists(dirs[i]+sysMOTD)){ sysMOTD.prepend(dirs[i]); break; }
  }

  QString tip;
  if(sysMOTD.contains("/") && LUtils::isValidBinary(sysMOTD)){
    //is binary - run it to generate text
    tip = LUtils::getCmdOutput(sysMOTD).join("\n");

  }else if(QFile::exists(sysMOTD)){
    //text file - read it to generate text
    tip = LUtils::readFile(sysMOTD).join("\n");

  }else{
    int index = qrand()%46; //Make sure this number matches the length of the case below (max value +1)
  switch(index){
    case 0:
	tip = tr("This desktop is powered by coffee, coffee, and more coffee."); break;
    case 1:
	tip = tr("Keep up with desktop news!")+"\n\nwww.lumina-desktop.org"; break;
    case 2:
	tip = tr("There is a full handbook of information about the desktop available online.")+"\n\nwww.lumina-desktop.org/handbook"; break;
    case 3:
	tip = tr("Want to change the interface? Everything is customizable in the desktop configuration!"); break;
    case 4:
	tip = tr("Lumina can easily reproduce the interface from most other desktop environments."); break;
    case 5:
	tip = tr("This desktop is generously sponsored by iXsystems")+"\n\nwww.ixsystems.com"; break;
    case 6:
	tip = "\""+tr("I have never been hurt by what I have not said")+"\"\n\n- Calvin Coolidge -"; break;
    case 7:
	tip = "\""+tr("Gotta have more cowbell!")+"\"\n\n- Christopher Walken (SNL) -"; break;
    case 8:
	tip = "\""+tr("Everything has its beauty but not everyone sees it.")+"\"\n\n- Confucius -"; break;
    case 9:
	tip = "\""+tr("Before God we are all equally wise - and equally foolish.")+"\"\n\n- Albert Einstein -"; break;
    case 10:
	tip = "\""+tr("We cannot do everything at once, but we can do something at once.")+"\"\n\n- Calvin Coolidge -"; break;
    case 11:
	tip = "\""+tr("One with the law is a majority.")+"\"\n\n- Calvin Coolidge -"; break;
    case 12:
	tip = "\""+tr("Don't expect to build up the weak by pulling down the strong.")+"\"\n\n- Calvin Coolidge -"; break;
    case 13:
	tip = "\""+tr("You can't know too much, but you can say too much.")+"\"\n\n- Calvin Coolidge -"; break;
    case 14:
	tip = "\""+tr("Duty is not collective; it is personal.")+"\"\n\n- Calvin Coolidge -"; break;
    case 15:
	tip = "\""+tr("Any society that would give up a little liberty to gain a little security will deserve neither and lose both.")+"\"\n\n- Benjamin Franklin -"; break;
    case 16:
	tip = "\""+tr("Never trust a computer you can’t throw out a window.")+"\"\n\n- Steve Wozniak -"; break;
    case 17:
	tip = "\""+tr("Study the past if you would define the future.")+"\"\n\n- Confucius -"; break;
    case 18:
	tip = "\""+tr("The way to get started is to quit talking and begin doing.")+"\"\n\n- Walt Disney -"; break;
    case 19:
	tip = "\""+tr("Ask and it will be given to you; search, and you will find; knock and the door will be opened for you.")+"\"\n\n- Jesus Christ -"; break;
    case 20:
	tip = "\""+tr("Start where you are. Use what you have.  Do what you can.")+"\"\n\n- Arthur Ashe -"; break;
    case 21:
	tip = "\""+tr("A person who never made a mistake never tried anything new.")+"\"\n\n- Albert Einstein -"; break;
    case 22:
	tip = "\""+tr("It does not matter how slowly you go as long as you do not stop.")+"\"\n\n- Confucius -"; break;
    case 23:
	tip = "\""+tr("Do what you can, where you are, with what you have.")+"\"\n\n- Theodore Roosevelt -"; break;
    case 24:
	tip = "\""+tr("Remember no one can make you feel inferior without your consent.")+"\"\n\n- Eleanor Roosevelt -"; break;
    case 25:
	tip = "\""+tr("It’s not the years in your life that count. It’s the life in your years.")+"\"\n\n- Abraham Lincoln -"; break;
    case 26:
	tip = "\""+tr("Either write something worth reading or do something worth writing.")+"\"\n\n- Benjamin Franklin -"; break;
    case 27:
	tip = "\""+tr("The only way to do great work is to love what you do.")+"\"\n\n- Steve Jobs -"; break;
    case 28:
	tip = "\""+tr("Political correctness is tyranny with manners.")+"\"\n\n- Charlton Heston -"; break;
    case 29:
	tip = "\""+tr("Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.")+"\"\n\n- Albert Einstein -"; break;
    case 30:
	tip = "\""+tr("I find that the harder I work, the more luck I seem to have.")+"\"\n\n- Thomas Jefferson -"; break;
    case 31:
	tip = "\""+tr("Do, or do not. There is no 'try'.")+"\"\n\n- Yoda -"; break;
    case 32:
	tip = "\""+tr("A mathematician is a device for turning coffee into theorems.")+"\"\n\n- Paul Erdos -"; break;
    case 33:
	tip = "\""+tr("Good people do not need laws to tell them to act responsibly, while bad people will find a way around the laws.")+"\"\n\n- Plato -"; break;
    case 34:
	tip = "\""+tr("Black holes are where God divided by zero.")+"\"\n\n- Steven Wright -"; break;
    case 35:
	tip = "\""+tr("It's kind of fun to do the impossible.")+"\"\n\n- Walt Disney -"; break;
    case 36:
	tip = "\""+tr("Knowledge speaks, but wisdom listens.")+"\"\n\n- Jimi Hendrix -"; break;
    case 37:
	tip = "\""+tr("A witty saying proves nothing.")+"\"\n\n- Voltaire -"; break;
    case 38:
	tip = "\""+tr("Success usually comes to those who are too busy to be looking for it.")+"\"\n\n- Henry David Thoreau -"; break;
    case 39:
	tip = "\""+tr("Well-timed silence hath more eloquence than speech.")+"\"\n\n- Martin Fraquhar Tupper -"; break;
    case 40:
	tip = "\""+tr("I have never let my schooling interfere with my education.")+"\"\n\n- Mark Twain -"; break;
    case 41:
	tip = "\""+tr("The best way to predict the future is to invent it.")+"\"\n\n- Alan Kay -"; break;
    case 42:
	tip = "\""+tr("Well done is better than well said.")+"\"\n\n- Benjamin Franklin -"; break;
    case 43:
	tip = "\""+tr("Sometimes it is not enough that we do our best; we must do what is required.")+"\"\n\n- Sir Winston Churchill -"; break;
    case 44:
	tip = "\""+tr("The truth is more important than the facts.")+"\"\n\n- Frank Lloyd Wright -"; break;
    case 45:
	tip = "\""+tr("Better to remain silent and be thought a fool than to speak out and remove all doubt.")+"\"\n\n- Abraham Lincoln -"; break;
  } //end of switch for tips

  } //end of fallback tip generation
  ui->label_welcome->setText( tip);
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session …"); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading System Settings …"); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Loading User Preferences …"); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Preparing System Tray …"); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager …"); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting Applications …"); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Preparing Menus …"); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Preparing Workspace …"); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Finalizing …"); per = 90;
    icon = "start-here-lumina";
  }else if(loading.startsWith("app::")){
    txt = QString(tr("Starting App: %1")).arg(loading.section("::",1,50)); per = -1;
  }
  if(per>0){ ui->progressBar->setValue(per); }
  else{ ui->progressBar->setRange(0,0); } //loading indicator
  ui->label_text->setText(txt);
  if(!icon.isEmpty()){ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) ); }
  this->raise();
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}
<|endoftext|>


<commit_before>#include <limits>

#include <Bull/Core/Log.hpp>

#include <Bull/Render/Context/Glx/GlxContext.hpp>
#include <Bull/Render/Context/Glx/GlxCreateContextARB.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlEXT.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlMESA.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlSGI.hpp>

#include <Bull/Utility/Window/X11/ErrorHandler.hpp>

namespace Bull
{
    namespace prv
    {
        void* GlxContext::getFunction(const String& function)
        {
            return reinterpret_cast<void*>(glXGetProcAddressARB(reinterpret_cast<const unsigned char*>(static_cast<const char*>(function))));
        }

        void GlxContext::requireExtensions(const ExtensionsLoader::Instance& loader)
        {
            loader->require(GlxCreateContextARB);

            if(isSupported(GlxSwapControlEXT))
            {
                loader->require(GlxSwapControlEXT);
            }
            else if(isSupported(GlxSwapControlMESA))
            {
                loader->require(GlxSwapControlMESA);
            }
            else if(isSupported(GlxSwapControlSGI))
            {
                loader->require(GlxSwapControlSGI);
            }
            else
            {
                Log::get()->write("VSync is not available on your system", Log::Level::Notice);
            }
        }

        GLXFBConfig GlxContext::chooseBestConfig(Display::Instance display, const ContextSettings& settings, unsigned int bitsPerPixel)
        {
            int attributes[] =
            {
                GLX_X_RENDERABLE  , True,
                GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
                GLX_RENDER_TYPE   , GLX_RGBA_BIT,
                GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
                GLX_RED_SIZE      , static_cast<int>(bitsPerPixel) / 4,
                GLX_GREEN_SIZE    , static_cast<int>(bitsPerPixel) / 4,
                GLX_BLUE_SIZE     , static_cast<int>(bitsPerPixel) / 4,
                GLX_ALPHA_SIZE    , static_cast<int>(bitsPerPixel) / 4,
                GLX_DEPTH_SIZE    , settings.depths,
                GLX_STENCIL_SIZE  , settings.stencil,
                GLX_DOUBLEBUFFER  , True,
                GLX_SAMPLE_BUFFERS, settings.antialiasing == 0 ? 0 : 1,
                GLX_SAMPLES       , settings.antialiasing,
                0
            };

            int fbCounts = 0;
            int bestConfig = 0, bestScore = std::numeric_limits<int>::max();
            GLXFBConfig config;
            GLXFBConfig* configs = glXChooseFBConfig(display->getHandler(), display->getDefaultScreen(), attributes, &fbCounts);

            for(int i = 0; i < fbCounts; i++)
            {
                XVisualInfo* visual = glXGetVisualFromFBConfig(display->getHandler(), configs[i]);

                if(visual)
                {
                    int red, green, blue, alpha;
                    int sampleBuffers, samples;
                    int depths, stencil;

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_RED_SIZE,   &red);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_GREEN_SIZE, &green);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_BLUE_SIZE,  &blue);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_ALPHA_SIZE, &alpha);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLE_BUFFERS, &sampleBuffers);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLES, &samples);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_DEPTH_SIZE,   &depths);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_STENCIL_SIZE, &stencil);

                    int currentBitsPerPixel = red + green + blue + alpha;
                    int score = evaluatePixelFormat(currentBitsPerPixel, depths, stencil, sampleBuffers ? samples : 0, bitsPerPixel, settings);

                    if(score < bestScore)
                    {
                        bestScore  = score;
                        bestConfig = i;
                    }
                }
            }

            config = configs[bestConfig];

            XFree(configs);

            return config;
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared) :
            GlxContext(shared, VideoMode(1, 1), ContextSettings())
        {
            /// Nothing
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, const VideoMode& mode, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(0),
            m_display(Display::get()),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, mode.bitsPerPixel);

            createSurface(mode.width, mode.height, mode.bitsPerPixel);

            if(m_window)
            {
                createContext(shared);
            }
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, unsigned int bitsPerPixel, const ContextSettings& settings) :
            GlxContext(shared, VideoMode(1, 1, bitsPerPixel), settings)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, WindowHandler window, unsigned int bitsPerPixel, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(0),
            m_display(Display::get()),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, bitsPerPixel);

            createSurface(window);

            if(window)
            {
                createContext(shared);
            }
        }

        GlxContext::~GlxContext()
        {
            if(m_ownWindow)
            {
                XDestroyWindow(m_display->getHandler(), m_window);
            }

            if(m_render)
            {
                if(glXGetCurrentContext() == m_render)
                {
                    glXMakeCurrent(m_display->getHandler(), 0, 0);
                }

                glXDestroyContext(m_display->getHandler(), m_render);
            }
        }

        void GlxContext::display()
        {
            if(m_window && m_render)
            {
                glXSwapBuffers(m_display->getHandler(), m_window);
            }
        }

        void GlxContext::enableVsync(bool active)
        {

        }

        SurfaceHandler GlxContext::getSurfaceHandler() const
        {
            return m_display->getDefaultScreen();
        }

        bool GlxContext::makeCurrent()
        {
            if(m_window && m_render)
            {
                ErrorHandler handler;
                return glXMakeCurrent(m_display->getHandler(), m_window, m_render) == True;
            }

            return false;
        }

        void GlxContext::createSurface(WindowHandler handler)
        {
            m_window = handler;
        }

        void GlxContext::createSurface(unsigned int width, unsigned int height, unsigned int bitsPerPixel)
        {
            XVisualInfo*         vi;
            GLXFBConfig          config;
            ErrorHandler         handler;
            XSetWindowAttributes attributes;

            config = GlxContext::chooseBestConfig(m_display, m_settings, bitsPerPixel);

            vi = glXGetVisualFromFBConfig(m_display->getHandler(), config);

            attributes.background_pixel = 0;
            attributes.border_pixel     = 0;
            attributes.colormap         = XCreateColormap(m_display->getHandler(), m_display->getRootWindow(vi->screen), vi->visual, AllocNone);

            m_window = XCreateWindow(m_display->getHandler(),
                                     m_display->getRootWindow(),
                                     0, 0,
                                     width, height,
                                     0,
                                     vi->depth,
                                     InputOnly,
                                     vi->visual,
                                     CWBackPixel | CWBorderPixel | CWColormap,
                                     &attributes);
        }

        void GlxContext::createContext(const std::shared_ptr<GlxContext>& shared)
        {
            GLXContext sharedHandler = shared.get() != nullptr ? shared->m_render : 0;

            int glxMajor, glxMinor;

            glXQueryVersion(m_display->getHandler(), &glxMajor, &glxMinor);

            if(isSupported(GlxCreateContextARB) && (glxMajor > 1 || glxMinor >= 3))
            {
                do
                {
                    ErrorHandler handler;
                    std::vector<int> attribs;

                    attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
                    attribs.push_back(m_settings.major);
                    attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
                    attribs.push_back(m_settings.minor);

                    int flags   = 0;
                    int profile = (m_settings.flags & ContextSettings::Compatibility) ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;

                    if(m_settings.flags & ContextSettings::Debug)
                    {
                        flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
                    }

                    if(m_settings.flags & ContextSettings::ForwardCompatible)
                    {
                        flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
                    }

                    attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
                    attribs.push_back(profile);
                    attribs.push_back(GLX_CONTEXT_FLAGS_ARB);
                    attribs.push_back(flags);

                    attribs.push_back(0);

                    m_render = glXCreateContextAttribs(m_display->getHandler(), m_config, sharedHandler, True, &attribs[0]);

                    if(!m_render)
                    {
                        if(m_settings.minor == 0)
                        {
                            m_settings.major -= 1;
                            m_settings.minor  = 9;
                        }
                        else
                        {
                            m_settings.minor -= 1;
                        }
                    }
                }while(!m_render && m_settings.major >= 1);
            }

            if(!m_render)
            {
                ErrorHandler handler;
                m_render = glXCreateNewContext(m_display->getHandler(), m_config, GLX_RGBA_TYPE, sharedHandler, True);
            }

            m_isDirect = glXIsDirect(m_display->getHandler(), m_render);
        }
    }
}
<commit_msg>Render/GlxContext Ensure GLX_ARB_create_context_profile is supported<commit_after>#include <limits>

#include <Bull/Core/Log.hpp>

#include <Bull/Render/Context/Glx/GlxContext.hpp>
#include <Bull/Render/Context/Glx/GlxCreateContextARB.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlEXT.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlMESA.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlSGI.hpp>

#include <Bull/Utility/Window/X11/ErrorHandler.hpp>

namespace Bull
{
    namespace prv
    {
        void* GlxContext::getFunction(const String& function)
        {
            return reinterpret_cast<void*>(glXGetProcAddressARB(reinterpret_cast<const unsigned char*>(static_cast<const char*>(function))));
        }

        void GlxContext::requireExtensions(const ExtensionsLoader::Instance& loader)
        {
            loader->require(GlxCreateContextARB);

            if(isSupported(GlxSwapControlEXT))
            {
                loader->require(GlxSwapControlEXT);
            }
            else if(isSupported(GlxSwapControlMESA))
            {
                loader->require(GlxSwapControlMESA);
            }
            else if(isSupported(GlxSwapControlSGI))
            {
                loader->require(GlxSwapControlSGI);
            }
            else
            {
                Log::get()->write("VSync is not available on your system", Log::Level::Notice);
            }
        }

        GLXFBConfig GlxContext::chooseBestConfig(Display::Instance display, const ContextSettings& settings, unsigned int bitsPerPixel)
        {
            int attributes[] =
            {
                GLX_X_RENDERABLE  , True,
                GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
                GLX_RENDER_TYPE   , GLX_RGBA_BIT,
                GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
                GLX_RED_SIZE      , static_cast<int>(bitsPerPixel) / 4,
                GLX_GREEN_SIZE    , static_cast<int>(bitsPerPixel) / 4,
                GLX_BLUE_SIZE     , static_cast<int>(bitsPerPixel) / 4,
                GLX_ALPHA_SIZE    , static_cast<int>(bitsPerPixel) / 4,
                GLX_DEPTH_SIZE    , settings.depths,
                GLX_STENCIL_SIZE  , settings.stencil,
                GLX_DOUBLEBUFFER  , True,
                GLX_SAMPLE_BUFFERS, settings.antialiasing == 0 ? 0 : 1,
                GLX_SAMPLES       , settings.antialiasing,
                0
            };

            int fbCounts = 0;
            int bestConfig = 0, bestScore = std::numeric_limits<int>::max();
            GLXFBConfig config;
            GLXFBConfig* configs = glXChooseFBConfig(display->getHandler(), display->getDefaultScreen(), attributes, &fbCounts);

            for(int i = 0; i < fbCounts; i++)
            {
                XVisualInfo* visual = glXGetVisualFromFBConfig(display->getHandler(), configs[i]);

                if(visual)
                {
                    int red, green, blue, alpha;
                    int sampleBuffers, samples;
                    int depths, stencil;

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_RED_SIZE,   &red);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_GREEN_SIZE, &green);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_BLUE_SIZE,  &blue);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_ALPHA_SIZE, &alpha);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLE_BUFFERS, &sampleBuffers);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLES, &samples);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_DEPTH_SIZE,   &depths);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_STENCIL_SIZE, &stencil);

                    int currentBitsPerPixel = red + green + blue + alpha;
                    int score = evaluatePixelFormat(currentBitsPerPixel, depths, stencil, sampleBuffers ? samples : 0, bitsPerPixel, settings);

                    if(score < bestScore)
                    {
                        bestScore  = score;
                        bestConfig = i;
                    }
                }
            }

            config = configs[bestConfig];

            XFree(configs);

            return config;
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared) :
            GlxContext(shared, VideoMode(1, 1), ContextSettings())
        {
            /// Nothing
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, const VideoMode& mode, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(0),
            m_display(Display::get()),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, mode.bitsPerPixel);

            createSurface(mode.width, mode.height, mode.bitsPerPixel);

            if(m_window)
            {
                createContext(shared);
            }
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, unsigned int bitsPerPixel, const ContextSettings& settings) :
            GlxContext(shared, VideoMode(1, 1, bitsPerPixel), settings)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const std::shared_ptr<GlxContext>& shared, WindowHandler window, unsigned int bitsPerPixel, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(0),
            m_display(Display::get()),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, bitsPerPixel);

            createSurface(window);

            if(window)
            {
                createContext(shared);
            }
        }

        GlxContext::~GlxContext()
        {
            if(m_ownWindow)
            {
                XDestroyWindow(m_display->getHandler(), m_window);
            }

            if(m_render)
            {
                if(glXGetCurrentContext() == m_render)
                {
                    glXMakeCurrent(m_display->getHandler(), 0, 0);
                }

                glXDestroyContext(m_display->getHandler(), m_render);
            }
        }

        void GlxContext::display()
        {
            if(m_window && m_render)
            {
                glXSwapBuffers(m_display->getHandler(), m_window);
            }
        }

        void GlxContext::enableVsync(bool active)
        {

        }

        SurfaceHandler GlxContext::getSurfaceHandler() const
        {
            return m_display->getDefaultScreen();
        }

        bool GlxContext::makeCurrent()
        {
            if(m_window && m_render)
            {
                ErrorHandler handler;
                return glXMakeCurrent(m_display->getHandler(), m_window, m_render) == True;
            }

            return false;
        }

        void GlxContext::createSurface(WindowHandler handler)
        {
            m_window = handler;
        }

        void GlxContext::createSurface(unsigned int width, unsigned int height, unsigned int bitsPerPixel)
        {
            XVisualInfo*         vi;
            GLXFBConfig          config;
            ErrorHandler         handler;
            XSetWindowAttributes attributes;

            config = GlxContext::chooseBestConfig(m_display, m_settings, bitsPerPixel);

            vi = glXGetVisualFromFBConfig(m_display->getHandler(), config);

            attributes.background_pixel = 0;
            attributes.border_pixel     = 0;
            attributes.colormap         = XCreateColormap(m_display->getHandler(), m_display->getRootWindow(vi->screen), vi->visual, AllocNone);

            m_window = XCreateWindow(m_display->getHandler(),
                                     m_display->getRootWindow(),
                                     0, 0,
                                     width, height,
                                     0,
                                     vi->depth,
                                     InputOnly,
                                     vi->visual,
                                     CWBackPixel | CWBorderPixel | CWColormap,
                                     &attributes);
        }

        void GlxContext::createContext(const std::shared_ptr<GlxContext>& shared)
        {
            GLXContext sharedHandler = shared.get() != nullptr ? shared->m_render : 0;

            int glxMajor, glxMinor;

            glXQueryVersion(m_display->getHandler(), &glxMajor, &glxMinor);

            if(isSupported(GlxCreateContextARB) && (glxMajor > 1 || glxMinor >= 3))
            {
                do
                {
                    ErrorHandler handler;
                    std::vector<int> attribs;

                    attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
                    attribs.push_back(m_settings.major);
                    attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
                    attribs.push_back(m_settings.minor);

                    if(isSupported("GLX_ARB_create_context_profile"))
                    {
                        int flags   = 0;
                        int profile = (m_settings.flags & ContextSettings::Compatibility) ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;

                        if(m_settings.flags & ContextSettings::Debug)
                        {
                            flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
                        }

                        if(m_settings.flags & ContextSettings::ForwardCompatible)
                        {
                            flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
                        }

                        attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
                        attribs.push_back(profile);
                        attribs.push_back(GLX_CONTEXT_FLAGS_ARB);
                        attribs.push_back(flags);
                    }

                    attribs.push_back(0);

                    m_render = glXCreateContextAttribs(m_display->getHandler(), m_config, sharedHandler, True, &attribs[0]);

                    if(!m_render)
                    {
                        if(m_settings.minor == 0)
                        {
                            m_settings.major -= 1;
                            m_settings.minor  = 9;
                        }
                        else
                        {
                            m_settings.minor -= 1;
                        }
                    }
                }while(!m_render && m_settings.major >= 1);
            }

            if(!m_render)
            {
                ErrorHandler handler;
                m_render = glXCreateNewContext(m_display->getHandler(), m_config, GLX_RGBA_TYPE, sharedHandler, True);
            }

            m_isDirect = glXIsDirect(m_display->getHandler(), m_render);
        }
    }
}
<|endoftext|>


<commit_before>#ifndef GIBBS_SAMPLER_HPP
#define GIBBS_SAMPLER_HPP
//#include "rejection_sampler_1d.hpp"
#include "base_urand.hpp"
//#include "arms.hpp"
#include "discrete_sample.hpp"
#include "continuous_sample.hpp"
#include <vector>
#include <memory>

namespace mcmc_utilities
{
  template <typename T_p,typename T_var>
  void gibbs_sample(const probability_density_md<T_p,T_var>& pd,T_var& init_var,base_urand<T_p>& rnd)
  {
    for(int i=0;i<get_size(init_var);++i)
      {
	auto xrange=pd.var_range(init_var,i);
	if(xrange.first>get_element(init_var,i)||xrange.second<get_element(init_var,i))
	  {
	    var_out_of_range e;
	    e.attach_message("gibbs sampler #1");
	    throw e;
	  }
      }

    size_t idx=0;
    typedef typename element_type_trait<T_var>::element_type T_var1;
    class conditional_probability_density
      :public probability_density_1d<typename element_type_trait<T_var>::element_type>
    {
    public:
      size_t* p_idx;
      T_var* p_init_var;
      const probability_density_md<T_p,T_var>* ppd;
    private:
      T_p do_eval_log(const T_var1& x1)const
      {
	set_element(*p_init_var,*p_idx,x1);
	T_p result= ppd->eval_log(*p_init_var,*p_idx);
	return result;
      }

      std::pair<T_var1,T_var1> do_var_range()const
      {
	//ppd->var_range(xmin,xmax,*p_init_var,(*p_idx));
	return ppd->var_range(*p_init_var,*p_idx);
      }

      std::vector<T_var1> do_init_points()const
      {
	//int n=ppd->num_init_points(*p_init_var,*p_idx);
	std::vector<T_var1> xinit(ppd->init_points(*p_init_var,*p_idx));
	if(xinit.size()==0)
	  {
	    xinit.resize(5);

	    std::pair<T_var1,T_var1> xrange(this->var_range());
	    T_var1 xl=xrange.first;
	    T_var1 xr=xrange.second;

	    for(size_t n1=0;n1<xinit.size();++n1)
	      {
		//if(n1!=1)
		  {
		    xinit[n1]= xl+(xr-xl)/(xinit.size()+1)*(n1+1);
		  }
		  //else
		  {
		    // xinit[n1]= find_peak(*this);
		  }
	      }
	  }
	return xinit;
      }

      std::vector<T_var1> do_candidate_points()const
      {
	return ppd->candidate_points(*p_init_var,*p_idx);
      }
    }cpd;
    cpd.p_idx=std::addressof(idx);
    cpd.p_init_var=std::addressof(init_var);
    cpd.ppd=std::addressof(pd);
    T_var1 xprev=0.;
    for(idx=0;idx<get_size(init_var);++idx)
      {
	xprev=get_element(init_var,idx);

	//T_var1 x=sampler.sample(cpd,xprev);
	//T_var1 x=arms(cpd,xprev,10,rnd);
	T_var1 x=continuous_sample([&](const T_var1& x){return cpd.eval_log(x);},cpd.var_range(),cpd.init_points(),xprev,10,rnd);
	set_element(init_var,idx,x);
      }
  }

  template <typename T_p,typename T_var,typename T_urand>
  void gibbs_sample1(const probability_density_md<T_p,T_var>& pd,
		    T_var& init_var,size_t idx,base_urand<T_p>& rnd)
  {
    for(int i=0;i<get_size(init_var);++i)
      {
	auto xrange=pd.var_range(init_var,i);
	if(xrange.first>get_element(init_var,i)||xrange.second<get_element(init_var,i))
	  {
	    var_out_of_range e;
	    e.attach_message("gibbs sampler #1");
	    throw e;
	  }
      }

    if(idx>=get_size(init_var))
      {
	throw index_out_of_range();
      }
    typedef typename element_type_trait<T_var>::element_type T_var1;
    class conditional_probability_density
      :public probability_density_1d<typename element_type_trait<T_var>::element_type>
    {
    public:
      size_t* p_idx;
      T_var* p_init_var;
      const probability_density_md<T_p,T_var>* ppd;
    private:
      T_p do_eval_log(const T_var1& x1)const
      {
	set_element(*p_init_var,*p_idx,x1);
	T_p result= ppd->eval_log(*p_init_var,*p_idx);
	return result;
      }

      std::pair<T_var1,T_var1> do_var_range()const
      {
	//ppd->var_range(xmin,xmax,*p_init_var,(*p_idx));
	return ppd->var_range(*p_init_var,*p_idx);
      }

      std::vector<T_var1> do_init_points()const
      {
	//int n=ppd->num_init_points(*p_init_var,*p_idx);
	std::vector<T_var1> xinit(ppd->init_points(*p_init_var,*p_idx));
	if(xinit.size()==0)
	  {
	    xinit.resize(5);

	    std::pair<T_var1,T_var1> xrange(this->var_range());
	    T_var1 xl=xrange.first;
	    T_var1 xr=xrange.second;

	    for(size_t n1=0;n1<xinit.size();++n1)
	      {
		//if(n1!=1)
		  {
		    xinit[n1]= xl+(xr-xl)/(xinit.size()+1)*(n1+1);
		  }
		  //else
		  {
		    //xinit[n1]= find_peak(*this);
		  }
	      }
	  }
	return xinit;
      }

      std::vector<T_var1> do_candidate_points()const
      {
	return ppd->candidate_points(*p_init_var,*p_idx);
      }

    }cpd;
    cpd.p_idx=std::addressof(idx);
    cpd.p_init_var=std::addressof(init_var);
    cpd.ppd=std::addressof(pd);
    T_var1 xprev=0.;

    xprev=get_element(init_var,idx);
    //T_var1 x=sampler.sample(cpd,xprev);
    //T_var1 x=arms(cpd,xprev,10,rnd);
    T_var1 x=continuous_sample([&](const T_var1& x){return cpd.eval_log(x);}, cpd.var_range(),cpd.init_points(),xprev,10,rnd);
    set_element(init_var,idx,x);
  }

};

#endif
<commit_msg>	修改：     core/gibbs_sampler.hpp<commit_after>#ifndef GIBBS_SAMPLER_HPP
#define GIBBS_SAMPLER_HPP
//#include "rejection_sampler_1d.hpp"
#include "base_urand.hpp"
//#include "arms.hpp"
#include "discrete_sample.hpp"
#include "continuous_sample.hpp"
#include <vector>
#include <memory>

namespace mcmc_utilities
{
  template <typename T_p,typename T_var>
  void gibbs_sample(const probability_density_md<T_p,T_var>& pd,T_var& init_var,base_urand<T_p>& rnd)
  {
    for(int i=0;i<get_size(init_var);++i)
      {
	auto xrange=pd.var_range(init_var,i);
	if(xrange.first>get_element(init_var,i)||xrange.second<get_element(init_var,i))
	  {
	    var_out_of_range e;
	    e.attach_message("gibbs sampler #1");
	    throw e;
	  }
      }

    size_t idx=0;
    typedef typename element_type_trait<T_var>::element_type T_var1;
    class conditional_probability_density
      :public probability_density_1d<typename element_type_trait<T_var>::element_type>
    {
    public:
      size_t* p_idx;
      T_var* p_init_var;
      const probability_density_md<T_p,T_var>* ppd;
    private:
      T_p do_eval_log(const T_var1& x1)const
      {
	set_element(*p_init_var,*p_idx,x1);
	T_p result= ppd->eval_log(*p_init_var,*p_idx);
	if(!std::isfinite(result))
	  {
	    std::cerr<<"inside gibbs:"<<std::endl;
	    std::cerr<<"x="<<x1<<std::endl;
	  }
	return result;
      }

      std::pair<T_var1,T_var1> do_var_range()const
      {
	//ppd->var_range(xmin,xmax,*p_init_var,(*p_idx));
	return ppd->var_range(*p_init_var,*p_idx);
      }

      std::vector<T_var1> do_init_points()const
      {
	//int n=ppd->num_init_points(*p_init_var,*p_idx);
	std::vector<T_var1> xinit(ppd->init_points(*p_init_var,*p_idx));
	if(xinit.size()==0)
	  {
	    xinit.resize(5);

	    std::pair<T_var1,T_var1> xrange(this->var_range());
	    T_var1 xl=xrange.first;
	    T_var1 xr=xrange.second;

	    for(size_t n1=0;n1<xinit.size();++n1)
	      {
		//if(n1!=1)
		  {
		    xinit[n1]= xl+(xr-xl)/(xinit.size()+1)*(n1+1);
		  }
		  //else
		  {
		    // xinit[n1]= find_peak(*this);
		  }
	      }
	  }
	return xinit;
      }

      std::vector<T_var1> do_candidate_points()const
      {
	return ppd->candidate_points(*p_init_var,*p_idx);
      }
    }cpd;
    cpd.p_idx=std::addressof(idx);
    cpd.p_init_var=std::addressof(init_var);
    cpd.ppd=std::addressof(pd);
    T_var1 xprev=0.;
    for(idx=0;idx<get_size(init_var);++idx)
      {
	xprev=get_element(init_var,idx);

	//T_var1 x=sampler.sample(cpd,xprev);
	//T_var1 x=arms(cpd,xprev,10,rnd);
	T_var1 x=continuous_sample([&](const T_var1& x){return cpd.eval_log(x);},cpd.var_range(),cpd.init_points(),xprev,10,rnd);
	set_element(init_var,idx,x);
      }
  }

  template <typename T_p,typename T_var,typename T_urand>
  void gibbs_sample1(const probability_density_md<T_p,T_var>& pd,
		    T_var& init_var,size_t idx,base_urand<T_p>& rnd)
  {
    for(int i=0;i<get_size(init_var);++i)
      {
	auto xrange=pd.var_range(init_var,i);
	if(xrange.first>get_element(init_var,i)||xrange.second<get_element(init_var,i))
	  {
	    var_out_of_range e;
	    e.attach_message("gibbs sampler #1");
	    throw e;
	  }
      }

    if(idx>=get_size(init_var))
      {
	throw index_out_of_range();
      }
    typedef typename element_type_trait<T_var>::element_type T_var1;
    class conditional_probability_density
      :public probability_density_1d<typename element_type_trait<T_var>::element_type>
    {
    public:
      size_t* p_idx;
      T_var* p_init_var;
      const probability_density_md<T_p,T_var>* ppd;
    private:
      T_p do_eval_log(const T_var1& x1)const
      {
	set_element(*p_init_var,*p_idx,x1);
	T_p result= ppd->eval_log(*p_init_var,*p_idx);
	return result;
      }

      std::pair<T_var1,T_var1> do_var_range()const
      {
	//ppd->var_range(xmin,xmax,*p_init_var,(*p_idx));
	return ppd->var_range(*p_init_var,*p_idx);
      }

      std::vector<T_var1> do_init_points()const
      {
	//int n=ppd->num_init_points(*p_init_var,*p_idx);
	std::vector<T_var1> xinit(ppd->init_points(*p_init_var,*p_idx));
	if(xinit.size()==0)
	  {
	    xinit.resize(5);

	    std::pair<T_var1,T_var1> xrange(this->var_range());
	    T_var1 xl=xrange.first;
	    T_var1 xr=xrange.second;

	    for(size_t n1=0;n1<xinit.size();++n1)
	      {
		//if(n1!=1)
		  {
		    xinit[n1]= xl+(xr-xl)/(xinit.size()+1)*(n1+1);
		  }
		  //else
		  {
		    //xinit[n1]= find_peak(*this);
		  }
	      }
	  }
	return xinit;
      }

      std::vector<T_var1> do_candidate_points()const
      {
	return ppd->candidate_points(*p_init_var,*p_idx);
      }

    }cpd;
    cpd.p_idx=std::addressof(idx);
    cpd.p_init_var=std::addressof(init_var);
    cpd.ppd=std::addressof(pd);
    T_var1 xprev=0.;

    xprev=get_element(init_var,idx);
    //T_var1 x=sampler.sample(cpd,xprev);
    //T_var1 x=arms(cpd,xprev,10,rnd);
    T_var1 x=continuous_sample([&](const T_var1& x){return cpd.eval_log(x);}, cpd.var_range(),cpd.init_points(),xprev,10,rnd);
    set_element(init_var,idx,x);
  }

};

#endif
<|endoftext|>


<commit_before>
#ifndef __LOG_SERIALIZER_HPP__
#define __LOG_SERIALIZER_HPP__

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <map>

#include "serializer/serializer.hpp"
#include "config/cmd_args.hpp"
#include "utils.hpp"

#include "metablock/metablock_manager.hpp"
#include "extents/extent_manager.hpp"
#include "lba/lba_list.hpp"
#include "data_block_manager.hpp"

struct block_magic_t;

/**
 * This is the log-structured serializer, the holiest of holies of
 * RethinkDB. Please treat it with courtesy, professionalism, and
 * respect that it deserves.
 */

/*
TODO: Consider the following situation:
1. Block A is stored at address X.
2. Client issues a read for block A at address X. It gets hung up in the OS somewhere.
3. Client issues a write for block A. Address Y is chosen. The write completes quickly.
4. The garbage collector recognizes that block A is no longer at address X, so it releases the
    extent containing address X.
5. Client issues a write for block B. Address X, which is now free, is chosen. The write completes
    quickly.
6. The read from step #2 finally gets performed, but because block B is now at address X, it gets
    the contents of block B instead of block A.
*/

/*
TODO: Consider the following situation:
1. The data block manager's current extent is X. From X to X+Y have been filled.
2. The data block manager fills the range from X+Y to X+Y+Z.
3. The server crashes before the metablock has been written
4. On restart, the server only remembers that there is data from X to X+Y.
5. The data block manager re-fills the range from X+Y to X+Y+Z.
6. The disk experiences fragmentation, possibly causing a slowdown.
*/

typedef lba_list_t lba_index_t;

struct log_serializer_metablock_t {
    extent_manager_t::metablock_mixin_t extent_manager_part;
    lba_index_t::metablock_mixin_t lba_index_part;
    data_block_manager_t::metablock_mixin_t data_block_manager_part;
    ser_transaction_id_t transaction_id;
};

typedef metablock_manager_t<log_serializer_metablock_t> mb_manager_t;

// Used internally
struct ls_block_writer_t;
struct ls_write_fsm_t;
struct ls_read_fsm_t;
struct ls_start_new_fsm_t;
struct ls_start_existing_fsm_t;

struct log_serializer_t :
    public serializer_t,
    private data_block_manager_t::shutdown_callback_t,
    private lba_index_t::shutdown_callback_t
{
    friend class ls_block_writer_t;
    friend class ls_write_fsm_t;
    friend class ls_read_fsm_t;
    friend class ls_start_new_fsm_t;
    friend class ls_start_existing_fsm_t;

public:
    /* Serializer configuration. dynamic_config_t is everything that can be changed from run
    to run; static_config_t is the parameters that are set when the database is created and
    cannot be changed after that. */
    typedef log_serializer_private_dynamic_config_t private_dynamic_config_t;
    typedef log_serializer_dynamic_config_t dynamic_config_t;
    typedef log_serializer_static_config_t static_config_t;

    dynamic_config_t *dynamic_config;
    private_dynamic_config_t *private_config;
    static_config_t static_config;

public:
    log_serializer_t(dynamic_config_t *dynamic_config, private_dynamic_config_t *private_dynamic_config);
    virtual ~log_serializer_t();

    struct check_callback_t {
        virtual void on_serializer_check(bool is_existing) = 0;
        virtual ~check_callback_t() {}
    };
    static void check_existing(const char *filename, check_callback_t *cb);

    /* start_new() or start_existing() must be called before the serializer can be used. If
    start_new() is called, a new database will be created. If start_existing() is called, the
    serializer will read from an existing database. */
    struct ready_callback_t {
        virtual void on_serializer_ready(log_serializer_t *) = 0;
        virtual ~ready_callback_t() {}
    };
    bool start_new(static_config_t *static_config, ready_callback_t *ready_cb);
    bool start_existing(ready_callback_t *ready_cb);

    /* Implementation of the serializer_t API */
    void *malloc();
    void *clone(void*); // clones a buf
    void free(void*);

    bool do_read(ser_block_id_t block_id, void *buf, read_callback_t *callback);
    bool do_write(write_t *writes, int num_writes, write_txn_callback_t *callback);
    block_size_t get_block_size();
    ser_block_id_t max_block_id();
    bool block_in_use(ser_block_id_t id);
    repli_timestamp get_recency(ser_block_id_t id);

    /* shutdown() should be called when you are done with the serializer.

    If the shutdown is done immediately, shutdown() will return 'true'. Otherwise, it will return
    'false' and then call the given callback when the shutdown is done. */
    struct shutdown_callback_t {
        virtual void on_serializer_shutdown(log_serializer_t *) = 0;
        virtual ~shutdown_callback_t() {}
    };
    bool shutdown(shutdown_callback_t *cb);

private:
    bool next_shutdown_step();
    shutdown_callback_t *shutdown_callback;

    enum shutdown_state_t {
        shutdown_begin,
        shutdown_waiting_on_serializer,
        shutdown_waiting_on_datablock_manager,
        shutdown_waiting_on_lba
    } shutdown_state;
    bool shutdown_in_one_shot;

    virtual void on_datablock_manager_shutdown();
    virtual void on_lba_shutdown();

public:
    // disable_gc should be called when you want to turn off the gc
    // temporarily.
    //
    // disable_gc will ALWAYS eventually call the callback.  It will
    // return 'true' (and will have already called the callback) if gc
    // is stopped immediately.
    typedef data_block_manager_t::gc_disable_callback_t gc_disable_callback_t;

    bool disable_gc(gc_disable_callback_t *cb);

    // enable_gc() should be called when you want to turn on the gc.
    // gc will be enabled immediately.  Always returns 'true' for
    // do_on_cpu.
    bool enable_gc();

    // The magic value used for "zero" buffers written upon deletion.
    static const block_magic_t zerobuf_magic;

private:
    typedef log_serializer_metablock_t metablock_t;
    void prepare_metablock(metablock_t *mb_buffer);

    void consider_start_gc();

    enum state_t {
        state_unstarted,
        state_starting_up,
        state_ready,
        state_shutting_down,
        state_shut_down,
    } state;

    const char *db_path;
    direct_file_t *dbfile;

    extent_manager_t *extent_manager;
    mb_manager_t *metablock_manager;
    lba_index_t *lba_index;
    data_block_manager_t *data_block_manager;

    /* The ls_write_fsm_ts organize themselves into a list so that they can be sure to
    write their metablocks in the correct order. last_write points to the most recent
    transaction that started but did not finish; new ls_write_fsm_ts use it to find the
    end of the list so they can append themselves to it. */
    ls_write_fsm_t *last_write;

    int active_write_count;

    ser_transaction_id_t current_transaction_id;

    /* Keeps track of buffers that are currently being written, so that if we get a read
    for a block ID that we are currently writing but is not on disk yet, we can return
    the most current version. */
    typedef std::map<
        ser_block_id_t, ls_block_writer_t*
        > block_writer_map_t;
    block_writer_map_t block_writer_map;

#ifndef NDEBUG
    metablock_t debug_mb_buffer;
#endif
};

#endif /* __LOG_SERIALIZER_HPP__ */
<commit_msg>added concurrency problem name for easier background lookup<commit_after>
#ifndef __LOG_SERIALIZER_HPP__
#define __LOG_SERIALIZER_HPP__

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <map>

#include "serializer/serializer.hpp"
#include "config/cmd_args.hpp"
#include "utils.hpp"

#include "metablock/metablock_manager.hpp"
#include "extents/extent_manager.hpp"
#include "lba/lba_list.hpp"
#include "data_block_manager.hpp"

struct block_magic_t;

/**
 * This is the log-structured serializer, the holiest of holies of
 * RethinkDB. Please treat it with courtesy, professionalism, and
 * respect that it deserves.
 */

/*
TODO: Consider the following situation:
1. Block A is stored at address X.
2. Client issues a read for block A at address X. It gets hung up in the OS somewhere.
3. Client issues a write for block A. Address Y is chosen. The write completes quickly.
4. The garbage collector recognizes that block A is no longer at address X, so it releases the
    extent containing address X.
5. Client issues a write for block B. Address X, which is now free, is chosen. The write completes
    quickly.
6. The read from step #2 finally gets performed, but because block B is now at address X, it gets
    the contents of block B instead of block A.

    This situation is generally known as (an example of) ABA problem in concurrency literature.
*/

/*
TODO: Consider the following situation:
1. The data block manager's current extent is X. From X to X+Y have been filled.
2. The data block manager fills the range from X+Y to X+Y+Z.
3. The server crashes before the metablock has been written
4. On restart, the server only remembers that there is data from X to X+Y.
5. The data block manager re-fills the range from X+Y to X+Y+Z.
6. The disk experiences fragmentation, possibly causing a slowdown.
*/

typedef lba_list_t lba_index_t;

struct log_serializer_metablock_t {
    extent_manager_t::metablock_mixin_t extent_manager_part;
    lba_index_t::metablock_mixin_t lba_index_part;
    data_block_manager_t::metablock_mixin_t data_block_manager_part;
    ser_transaction_id_t transaction_id;
};

typedef metablock_manager_t<log_serializer_metablock_t> mb_manager_t;

// Used internally
struct ls_block_writer_t;
struct ls_write_fsm_t;
struct ls_read_fsm_t;
struct ls_start_new_fsm_t;
struct ls_start_existing_fsm_t;

struct log_serializer_t :
    public serializer_t,
    private data_block_manager_t::shutdown_callback_t,
    private lba_index_t::shutdown_callback_t
{
    friend class ls_block_writer_t;
    friend class ls_write_fsm_t;
    friend class ls_read_fsm_t;
    friend class ls_start_new_fsm_t;
    friend class ls_start_existing_fsm_t;

public:
    /* Serializer configuration. dynamic_config_t is everything that can be changed from run
    to run; static_config_t is the parameters that are set when the database is created and
    cannot be changed after that. */
    typedef log_serializer_private_dynamic_config_t private_dynamic_config_t;
    typedef log_serializer_dynamic_config_t dynamic_config_t;
    typedef log_serializer_static_config_t static_config_t;

    dynamic_config_t *dynamic_config;
    private_dynamic_config_t *private_config;
    static_config_t static_config;

public:
    log_serializer_t(dynamic_config_t *dynamic_config, private_dynamic_config_t *private_dynamic_config);
    virtual ~log_serializer_t();

    struct check_callback_t {
        virtual void on_serializer_check(bool is_existing) = 0;
        virtual ~check_callback_t() {}
    };
    static void check_existing(const char *filename, check_callback_t *cb);

    /* start_new() or start_existing() must be called before the serializer can be used. If
    start_new() is called, a new database will be created. If start_existing() is called, the
    serializer will read from an existing database. */
    struct ready_callback_t {
        virtual void on_serializer_ready(log_serializer_t *) = 0;
        virtual ~ready_callback_t() {}
    };
    bool start_new(static_config_t *static_config, ready_callback_t *ready_cb);
    bool start_existing(ready_callback_t *ready_cb);

    /* Implementation of the serializer_t API */
    void *malloc();
    void *clone(void*); // clones a buf
    void free(void*);

    bool do_read(ser_block_id_t block_id, void *buf, read_callback_t *callback);
    bool do_write(write_t *writes, int num_writes, write_txn_callback_t *callback);
    block_size_t get_block_size();
    ser_block_id_t max_block_id();
    bool block_in_use(ser_block_id_t id);
    repli_timestamp get_recency(ser_block_id_t id);

    /* shutdown() should be called when you are done with the serializer.

    If the shutdown is done immediately, shutdown() will return 'true'. Otherwise, it will return
    'false' and then call the given callback when the shutdown is done. */
    struct shutdown_callback_t {
        virtual void on_serializer_shutdown(log_serializer_t *) = 0;
        virtual ~shutdown_callback_t() {}
    };
    bool shutdown(shutdown_callback_t *cb);

private:
    bool next_shutdown_step();
    shutdown_callback_t *shutdown_callback;

    enum shutdown_state_t {
        shutdown_begin,
        shutdown_waiting_on_serializer,
        shutdown_waiting_on_datablock_manager,
        shutdown_waiting_on_lba
    } shutdown_state;
    bool shutdown_in_one_shot;

    virtual void on_datablock_manager_shutdown();
    virtual void on_lba_shutdown();

public:
    // disable_gc should be called when you want to turn off the gc
    // temporarily.
    //
    // disable_gc will ALWAYS eventually call the callback.  It will
    // return 'true' (and will have already called the callback) if gc
    // is stopped immediately.
    typedef data_block_manager_t::gc_disable_callback_t gc_disable_callback_t;

    bool disable_gc(gc_disable_callback_t *cb);

    // enable_gc() should be called when you want to turn on the gc.
    // gc will be enabled immediately.  Always returns 'true' for
    // do_on_cpu.
    bool enable_gc();

    // The magic value used for "zero" buffers written upon deletion.
    static const block_magic_t zerobuf_magic;

private:
    typedef log_serializer_metablock_t metablock_t;
    void prepare_metablock(metablock_t *mb_buffer);

    void consider_start_gc();

    enum state_t {
        state_unstarted,
        state_starting_up,
        state_ready,
        state_shutting_down,
        state_shut_down,
    } state;

    const char *db_path;
    direct_file_t *dbfile;

    extent_manager_t *extent_manager;
    mb_manager_t *metablock_manager;
    lba_index_t *lba_index;
    data_block_manager_t *data_block_manager;

    /* The ls_write_fsm_ts organize themselves into a list so that they can be sure to
    write their metablocks in the correct order. last_write points to the most recent
    transaction that started but did not finish; new ls_write_fsm_ts use it to find the
    end of the list so they can append themselves to it. */
    ls_write_fsm_t *last_write;

    int active_write_count;

    ser_transaction_id_t current_transaction_id;

    /* Keeps track of buffers that are currently being written, so that if we get a read
    for a block ID that we are currently writing but is not on disk yet, we can return
    the most current version. */
    typedef std::map<
        ser_block_id_t, ls_block_writer_t*
        > block_writer_map_t;
    block_writer_map_t block_writer_map;

#ifndef NDEBUG
    metablock_t debug_mb_buffer;
#endif
};

#endif /* __LOG_SERIALIZER_HPP__ */
<|endoftext|>


<commit_before>#include "DebugDrawingManager.hpp"

#include "Managers.hpp"
#include "ResourceManager.hpp"
#include "../Shader/Shader.hpp"
#include "../Shader/ShaderProgram.hpp"
#include "DebugDrawing.vert.hpp"
#include "DebugDrawing.frag.hpp"

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))

DebugDrawingManager::DebugDrawingManager() {
    vertexShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_VERT, DEBUGDRAWING_VERT_LENGTH, GL_VERTEX_SHADER);
    fragmentShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_FRAG, DEBUGDRAWING_FRAG_LENGTH, GL_FRAGMENT_SHADER);
    shaderProgram = Managers().resourceManager->CreateShaderProgram({ vertexShader, fragmentShader });

    // Create point vertex array.
    glBindVertexArray(0);

    glGenBuffers(1, &pointVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 1 * sizeof(glm::vec3), &glm::vec3(0.f, 0.f, 0.f)[0], GL_STATIC_DRAW);

    glGenVertexArrays(1, &pointVertexArray);
    glBindVertexArray(pointVertexArray);

    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);
}

DebugDrawingManager::~DebugDrawingManager() {
    glDeleteBuffers(1, &pointVertexBuffer);
    glDeleteVertexArrays(1, &pointVertexArray);

    Managers().resourceManager->FreeShader(vertexShader);
    Managers().resourceManager->FreeShader(fragmentShader);
    Managers().resourceManager->FreeShaderProgram(shaderProgram);
}

void DebugDrawingManager::AddPoint(const glm::vec3& position, const glm::vec3& color, float duration, bool depthTesting) {
    Point point;
    point.position = position;
    point.color = color;
    point.duration = duration;
    point.depthTesting = depthTesting;
    points.push_back(point);
}

void DebugDrawingManager::Update(float deltaTime) {
    /// @todo Update durations and remove old things.
}

void DebugDrawingManager::Render(Scene& scene) {
    shaderProgram->Use();

    // Points.
    glBindVertexArray(pointVertexArray);
    for (const Point& point : points) {
        glUniform3fv(shaderProgram->GetUniformLocation("color"), 1, &point.color[0]);
        glDrawArrays(GL_POINTS, 0, 1);
    }

    glBindVertexArray(0);
}
<commit_msg>Remove debug entities after duration ends<commit_after>#include "DebugDrawingManager.hpp"

#include "Managers.hpp"
#include "ResourceManager.hpp"
#include "../Shader/Shader.hpp"
#include "../Shader/ShaderProgram.hpp"
#include "DebugDrawing.vert.hpp"
#include "DebugDrawing.frag.hpp"

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))

DebugDrawingManager::DebugDrawingManager() {
    vertexShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_VERT, DEBUGDRAWING_VERT_LENGTH, GL_VERTEX_SHADER);
    fragmentShader = Managers().resourceManager->CreateShader(DEBUGDRAWING_FRAG, DEBUGDRAWING_FRAG_LENGTH, GL_FRAGMENT_SHADER);
    shaderProgram = Managers().resourceManager->CreateShaderProgram({ vertexShader, fragmentShader });

    // Create point vertex array.
    glBindVertexArray(0);

    glGenBuffers(1, &pointVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 1 * sizeof(glm::vec3), &glm::vec3(0.f, 0.f, 0.f)[0], GL_STATIC_DRAW);

    glGenVertexArrays(1, &pointVertexArray);
    glBindVertexArray(pointVertexArray);

    glBindBuffer(GL_ARRAY_BUFFER, pointVertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0));

    glBindVertexArray(0);
}

DebugDrawingManager::~DebugDrawingManager() {
    glDeleteBuffers(1, &pointVertexBuffer);
    glDeleteVertexArrays(1, &pointVertexArray);

    Managers().resourceManager->FreeShader(vertexShader);
    Managers().resourceManager->FreeShader(fragmentShader);
    Managers().resourceManager->FreeShaderProgram(shaderProgram);
}

void DebugDrawingManager::AddPoint(const glm::vec3& position, const glm::vec3& color, float duration, bool depthTesting) {
    Point point;
    point.position = position;
    point.color = color;
    point.duration = duration;
    point.depthTesting = depthTesting;
    points.push_back(point);
}

void DebugDrawingManager::Update(float deltaTime) {
    // Points.
    for (std::size_t i=0; i<points.size(); ++i) {
        if (points[i].duration < 0.f) {
            points[i] = points[points.size() - 1];
            points.pop_back();
            --i;
        } else {
            points[i].duration -= deltaTime;
        }
    }
}

void DebugDrawingManager::Render(Scene& scene) {
    shaderProgram->Use();

    // Points.
    glBindVertexArray(pointVertexArray);
    for (const Point& point : points) {
        glUniform3fv(shaderProgram->GetUniformLocation("color"), 1, &point.color[0]);
        glDrawArrays(GL_POINTS, 0, 1);
    }

    glBindVertexArray(0);
}
<|endoftext|>


<commit_before>#pragma once
/*
* Cross-platform DLL library
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#include <stdexcept>
#include <string>

#if defined(_WIN32) || defined(WIN32)

#include <windows.h>

namespace cov {
	class dll final {
		HMODULE m_handle = nullptr;
	public:
		dll() = default;

		dll(const dll &) = delete;

		explicit dll(const std::string &path)
		{
			open(path);
		}

		~dll()
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
		}

		bool is_open() const noexcept
		{
			return m_handle != nullptr;
		}

		void open(const std::string &path)
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
			m_handle = ::LoadLibrary(path.c_str());
			if (m_handle == nullptr) {
				static char szBuf[128];
				const char *args[] = {path.c_str()};
				::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, nullptr, ::GetLastError(),
				                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &szBuf, 128, (va_list *) args);
				throw std::logic_error(szBuf);
			}
		}

		void close()
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
			m_handle = nullptr;
		}

		void *get_address(const std::string &method)
		{
			if (m_handle == nullptr)
				throw std::logic_error("Used an unopened file.");
			return reinterpret_cast<void *>(::GetProcAddress(m_handle, method.c_str()));
		}
	};
}
#else

#include <dlfcn.h>

namespace cov {
	class dll final {
		void *m_handle = nullptr;
	public:
		dll() = default;

		dll(const dll &) = delete;

		dll(const std::string &path)
		{
			open(path);
		}

		~dll()
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
		}

		bool is_open() const noexcept
		{
			return m_handle != nullptr;
		}

		void open(const std::string &path)
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
			m_handle = ::dlopen(path.c_str(), RTLD_NOW);
			if (m_handle == nullptr)
				throw std::logic_error(::dlerror());
		}

		void close()
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
			m_handle = nullptr;
		}

		void *get_address(const std::string &method)
		{
			if (m_handle == nullptr)
				throw std::logic_error("Used an unopened file.");
			return ::dlsym(m_handle, method.c_str());
		}
	};
}
#endif<commit_msg>Update dll.hpp<commit_after>#pragma once
/*
* Cross-platform DLL library
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#include <stdexcept>
#include <string>

#if defined(_WIN32) || defined(WIN32)

#include <windows.h>

namespace cov {
	class dll final {
		HMODULE m_handle = nullptr;
	public:
		dll() = default;

		dll(const dll &) = delete;

		explicit dll(const std::string &path)
		{
			open(path);
		}

		~dll()
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
		}

		bool is_open() const noexcept
		{
			return m_handle != nullptr;
		}

		void open(const std::string &path)
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
			m_handle = ::LoadLibrary(path.c_str());
			if (m_handle == nullptr) {
				static char szBuf[128];
				const char *args[] = {path.c_str()};
				::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, nullptr, ::GetLastError(),
				                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &szBuf, 128, (va_list *) args);
				throw std::logic_error(szBuf);
			}
		}

		void close()
		{
			if (m_handle != nullptr)
				::FreeLibrary(m_handle);
			m_handle = nullptr;
		}

		void *get_address(const std::string &method)
		{
			if (m_handle == nullptr)
				throw std::logic_error("Used an unopened file.");
			return reinterpret_cast<void *>(::GetProcAddress(m_handle, method.c_str()));
		}
	};
}
#else

#include <dlfcn.h>

namespace cov {
	class dll final {
		void *m_handle = nullptr;
	public:
		dll() = default;

		dll(const dll &) = delete;

		dll(const std::string &path)
		{
			open(path);
		}

		~dll()
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
		}

		bool is_open() const noexcept
		{
			return m_handle != nullptr;
		}

		void open(const std::string &path)
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
			m_handle = ::dlopen(path.c_str(), RTLD_LAZY | RTLD_DEEPBIND);
			if (m_handle == nullptr)
				throw std::logic_error(::dlerror());
		}

		void close()
		{
			if (m_handle != nullptr)
				::dlclose(m_handle);
			m_handle = nullptr;
		}

		void *get_address(const std::string &method)
		{
			if (m_handle == nullptr)
				throw std::logic_error("Used an unopened file.");
			return ::dlsym(m_handle, method.c_str());
		}
	};
}
#endif<|endoftext|>


<commit_before>// Copyright 2012-2013 Samplecount S.L.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED
#define METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED

#include <array>
#include <atomic>
#include <functional>
#include <thread>

#include <boost/lockfree/spsc_queue.hpp>
#include <boost/utility.hpp>

#include "Methcla/Utility/Semaphore.hpp"

namespace Methcla { namespace Utility {

//* MWSR queue for sending commands to the engine.
// Request payload lifetime: from request until response callback.
// Caller is responsible for freeing request payload after the response callback has been called.
template <typename T, size_t queueSize> class MessageQueue : boost::noncopyable
{
public:
    inline void send(const T& msg)
    {
        std::lock_guard<std::mutex> lock(m_writeMutex);
        bool success = m_queue.push(msg);
        if (!success) throw std::runtime_error("Message queue overflow");
    }

    inline bool next(T& msg)
    {
        return m_queue.pop(msg);
    }

private:
    typedef boost::lockfree::spsc_queue<T,boost::lockfree::capacity<queueSize>> Queue;
    Queue      m_queue;
    std::mutex m_writeMutex;
};

template <typename Command, size_t queueSize> class Channel : boost::noncopyable
{
public:
    typedef std::function<void()> CommitHook;

    Channel(const CommitHook& afterCommit)
        // : m_queue(queueSize)
        : m_afterCommit(afterCommit)
    { }

    void send(const Command& cmd)
    {
        bool success = m_queue.push(cmd);
        BOOST_ASSERT( success );
        if (m_afterCommit) m_afterCommit();
    }

protected:
    typedef boost::lockfree::spsc_queue<Command,boost::lockfree::capacity<queueSize>> Queue;
    Queue      m_queue;
    CommitHook m_afterCommit;
};

template <typename Command, size_t queueSize> class Worker : boost::noncopyable
{
public:
    Worker()
        : m_toWorker([this](){ this->signalWorker(); })
        , m_fromWorker(typename Channel<Command,queueSize>::CommitHook())
    { }

    Channel<Command,queueSize>& toWorker()
    {
        return m_toWorker;
    }

    void perform()
    {
        drain(m_fromWorker, m_toWorker);
    }

protected:
    void work()
    {
        drain(m_toWorker, m_fromWorker);
    }

    virtual void signalWorker() { }

private:
    class Transport : public Channel<Command,queueSize>
    {
    public:
        Transport(const typename Channel<Command,queueSize>::CommitHook& afterCommit)
            : Channel<Command,queueSize>(afterCommit)
        { }

        bool dequeue(Command& cmd)
        {
            return this->m_queue.pop(cmd);
        }
    };

    inline static void drain(Transport& input, Transport& output)
    {
        for (;;) {
            Command cmd;
            bool success = input.dequeue(cmd);
            if (success) cmd.perform(output);
            else break;
        }
    }

private:
    Transport   m_toWorker;
    Transport   m_fromWorker;
};

template <typename Command, size_t queueSize> class WorkerThread : public Worker<Command, queueSize>
{
public:
    WorkerThread()
        : m_continue(true)
    {
        m_thread = std::thread(&WorkerThread::process, this);
    }
    ~WorkerThread()
    {
        m_continue.store(false, std::memory_order_acquire);
        m_sem.post();
        m_thread.join();
    }

private:
    void process()
    {
        for (;;) {
            m_sem.wait();
            bool cont = m_continue.load(std::memory_order_release);
            if (cont) {
                this->work();
            } else {
                break;
            }
        }
    }

    virtual void signalWorker() override
    {
        m_sem.post();
    }

private:
    std::thread       m_thread;
    Semaphore         m_sem;
    std::atomic<bool> m_continue;
};

}; };

#endif // METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED
<commit_msg>Throw runtime_error instead of using assert<commit_after>// Copyright 2012-2013 Samplecount S.L.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED
#define METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED

#include <array>
#include <atomic>
#include <functional>
#include <thread>

#include <boost/lockfree/spsc_queue.hpp>
#include <boost/utility.hpp>

#include "Methcla/Utility/Semaphore.hpp"

namespace Methcla { namespace Utility {

//* MWSR queue for sending commands to the engine.
// Request payload lifetime: from request until response callback.
// Caller is responsible for freeing request payload after the response callback has been called.
template <typename T, size_t queueSize> class MessageQueue : boost::noncopyable
{
public:
    inline void send(const T& msg)
    {
        std::lock_guard<std::mutex> lock(m_writeMutex);
        bool success = m_queue.push(msg);
        if (!success) throw std::runtime_error("Message queue overflow");
    }

    inline bool next(T& msg)
    {
        return m_queue.pop(msg);
    }

private:
    typedef boost::lockfree::spsc_queue<T,boost::lockfree::capacity<queueSize>> Queue;
    Queue      m_queue;
    std::mutex m_writeMutex;
};

template <typename Command, size_t queueSize> class Channel : boost::noncopyable
{
public:
    typedef std::function<void()> CommitHook;

    Channel(const CommitHook& afterCommit)
        // : m_queue(queueSize)
        : m_afterCommit(afterCommit)
    { }

    void send(const Command& cmd)
    {
        bool success = m_queue.push(cmd);
        if (!success) throw std::runtime_error("Channel overflow");
        if (m_afterCommit) m_afterCommit();
    }

protected:
    typedef boost::lockfree::spsc_queue<Command,boost::lockfree::capacity<queueSize>> Queue;
    Queue      m_queue;
    CommitHook m_afterCommit;
};

template <typename Command, size_t queueSize> class Worker : boost::noncopyable
{
public:
    Worker()
        : m_toWorker([this](){ this->signalWorker(); })
        , m_fromWorker(typename Channel<Command,queueSize>::CommitHook())
    { }

    Channel<Command,queueSize>& toWorker()
    {
        return m_toWorker;
    }

    void perform()
    {
        drain(m_fromWorker, m_toWorker);
    }

protected:
    void work()
    {
        drain(m_toWorker, m_fromWorker);
    }

    virtual void signalWorker() { }

private:
    class Transport : public Channel<Command,queueSize>
    {
    public:
        Transport(const typename Channel<Command,queueSize>::CommitHook& afterCommit)
            : Channel<Command,queueSize>(afterCommit)
        { }

        bool dequeue(Command& cmd)
        {
            return this->m_queue.pop(cmd);
        }
    };

    inline static void drain(Transport& input, Transport& output)
    {
        for (;;) {
            Command cmd;
            bool success = input.dequeue(cmd);
            if (success) cmd.perform(output);
            else break;
        }
    }

private:
    Transport   m_toWorker;
    Transport   m_fromWorker;
};

template <typename Command, size_t queueSize> class WorkerThread : public Worker<Command, queueSize>
{
public:
    WorkerThread()
        : m_continue(true)
    {
        m_thread = std::thread(&WorkerThread::process, this);
    }
    ~WorkerThread()
    {
        m_continue.store(false, std::memory_order_acquire);
        m_sem.post();
        m_thread.join();
    }

private:
    void process()
    {
        for (;;) {
            m_sem.wait();
            bool cont = m_continue.load(std::memory_order_release);
            if (cont) {
                this->work();
            } else {
                break;
            }
        }
    }

    virtual void signalWorker() override
    {
        m_sem.post();
    }

private:
    std::thread       m_thread;
    Semaphore         m_sem;
    std::atomic<bool> m_continue;
};

}; };

#endif // METHCLA_UTILITY_MESSAGEQUEUE_HPP_INCLUDED
<|endoftext|>