Pthread/tutorial

From WiiBrew
Jump to navigation Jump to search

PThread tutorial

POSIX Threads Programming tutorial, it's for pthreads in general so not everything will work with this but it's worth a read.

Bad tutorial by Mavakadachi

This source compile under windows using the pthread port http://sourceware.org/pthreads-win32/ Mac OSX and linux untested, wii obviously works :) you'll need the Pthread custom header

#ifdef _WIN32
    #include <windows.h>
    #pragma comment(lib, "pthreadVC2")
#else
    #include <unistd.h>
    void Sleep(unsigned long milliseconds)
    {
        if (milliseconds<1000)
            usleep(milliseconds*1000);
        else
            sleep(milliseconds/1000);
    }
#endif

#include <cassert>
#include <deque>
#include <stdexcept>
#include <pthread.h>

#include <ios>
#include <iostream>



using namespace std;

struct yourclass
{
};

typedef yourclass AppClass;

void unpackApp(AppClass &p)
{
    Sleep(100);
}
/*
static volatile bool MyQuit=0;
void iWantToQuit()
{
    MyQuit = 1;
}
*/

#define SingleInstancePlz static int SingleInstancePlz_=0; assert(SingleInstancePlz_==0); SingleInstancePlz_++;
class DownloadApp
{
    pthread_t thread;
    pthread_mutex_t mutex;


    bool isDLing; //quitOnFinish;
    deque<AppClass> v;

    void *process()
    {
        AppClass app;
// bool wantExit=0;

        //dont want to pop and push_back at once, maybe its ok but lets not risk it
        pthread_mutex_lock(&mutex);

        while (v.size())
        {
            app = v.front();
            pthread_mutex_unlock(&mutex);
            unpackApp(app);
            pthread_mutex_lock(&mutex);

            v.pop_front();
        }
        isDLing = 0;
// wantExit = quitOnFinish;
        pthread_mutex_unlock(&mutex);
        //if (wantExit)            return iWantToQuit();
        return 0;
    }

    static void* Sprocess(void *p) {
        return ((DownloadApp*)p)->process();

    }
public:
    DownloadApp() { /*quitOnFinish=*/isDLing=0;
        SingleInstancePlz
        if (pthread_mutex_init(&mutex, 0))
            throw std::runtime_error("pthread_mutex_init failed");
    }
    ~DownloadApp() {
        //pthread_cancel(thread);
        pthread_mutex_destroy(&mutex);

    }

    bool isDownloading() //returns true if app is not done
    {
        bool ret;
        pthread_mutex_lock(&mutex);
        ret = isDLing;
        pthread_mutex_unlock(&mutex);

        return ret;
    }
    void startDownload(const AppClass &v_)
    {
        pthread_mutex_lock(&mutex);

        v.push_back(v_);
        if (isDLing == 0)
        {
            isDLing = 1;
            if (pthread_create(&thread, 0, Sprocess, this))
            {
                throw std::runtime_error("Error on pthread_create in ConsoleWantQuit::launch");
            }
        }
        pthread_mutex_unlock(&mutex);

    }
    /*
    void quitWhenFinish(bool b) //true will quit when all apps are done, kind of pointless but maybe users would like this
    {
        bool plzQuit=0;
        pthread_mutex_lock(&mutex);

        quitOnFinish = b;
        if (quitOnFinish && v.size() == 0)
            plzQuit=1;
        pthread_mutex_unlock(&mutex);
        if (plzQuit)
            iWantToQuit();
    }
    */
};



#ifdef HW_RVL
int main2();

#include <wiiuse/wpad.h>

static void *xfb = NULL;
static GXRModeObj *rmode = NULL;

//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------

    // Initialise the video system
    VIDEO_Init();
   
    // This function initialises the attached controllers
    WPAD_Init();
   
    // Obtain the preferred video mode from the system
    // This will correspond to the settings in the Wii menu
    rmode = VIDEO_GetPreferredMode(NULL);

    // Allocate memory for the display in the uncached region
    xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
   
    // Initialise the console, required for printf
    console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
   
    // Set up the video registers with the chosen mode
    VIDEO_Configure(rmode);
   
    // Tell the video hardware where our display memory is
    VIDEO_SetNextFramebuffer(xfb);
   
    // Make the display visible
    VIDEO_SetBlack(FALSE);

    // Flush the video register changes to the hardware
    VIDEO_Flush();

    // Wait for Video setup to complete
    VIDEO_WaitVSync();
    if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();


    // The console understands VT terminal escape codes
    // This positions the cursor on row 2, column 0
    // we can use variables for this with format codes too
    // e.g. printf ("\x1b[%d;%dH", row, column );
    printf("\x1b[2;0H");
   

    printf("Hello World!");
    main2();
    while(1) {

        // Call WPAD_ScanPads each loop, this reads the latest controller states
        WPAD_ScanPads();

        // WPAD_ButtonsDown tells us which buttons were pressed in this loop
        // this is a "one shot" state which will not fire again until the button has been released
        u32 pressed = WPAD_ButtonsDown(0);

        // We return to the launcher application via exit
        if ( pressed & WPAD_BUTTON_HOME ) exit(0);

        // Wait for the next frame
        VIDEO_WaitVSync();
    }

    return 0;
}
#define main main2
#endif


int main()
{

    {
    yourclass var;
    DownloadApp appDl;
    appDl.startDownload(var);
    Sleep(50);
    cout << appDl.isDownloading(); //shouldnt be done
    Sleep(70);
    cout << appDl.isDownloading(); //should be done

    appDl.startDownload(var);
    appDl.startDownload(var);
    Sleep(50+70+50);
    cout << appDl.isDownloading(); //shouldnt be done
    //appDl.quitWhenFinish(1);
    while (appDl.isDownloading())
    {
#ifdef HW_RVL
        WPAD_ScanPads();
        u32 pressed = WPAD_ButtonsDown(0);
        if ( pressed & WPAD_BUTTON_PLUS )
        {
            printf("i give\n");
            break;
        }
// VIDEO_WaitVSync();
#endif
        Sleep(10);

    }
    return 0;