//
// anyRemote
// a wi-fi or bluetooth remote for your PC.
//
// Copyright (C) 2006-2016 Mikhail Fedotov <anyremote@mail.ru>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

//
// Thread related wrappers
//

#include <stdio.h>
#include <stdlib.h>

#include "common.h"
#include "thread.h"

extern char tmp[MAXMAXLEN];

#ifdef USE_GLIB

GThread* _threads[T_MAX] = {NULL};

#if 0
//GLIB_MAJOR_VERSION >=2 && GLIB_MINOR_VERSION >= 32

void threadInit(void)
{
}

// how to create detached threads ?

int threadNew(int id, ThreadFunction func, void* data, int param)
{
    GThread* t = NULL;
    //gboolean join = (param == JOINABLE ? TRUE : FALSE);
    char buf[32];
    sprintf(buf,"%d",id);
    t = g_thread_new (buf, func, data);
    if (id >=0 && id < T_MAX && _threads[id] == NULL) {
        _threads[id] = t;
    }
    
    return (t ? RC_OK : RC_NOK);
}

#else

// GLIB 2.31 and older


void threadInit(void)
{
    g_thread_init(NULL);  // init GLIB thread subsystem
}

int threadNew(int id, ThreadFunction func, void* data, int param)
{
    GThread* t = NULL;
    gboolean join = (param == JOINABLE ? TRUE : FALSE);
    
    t = g_thread_create (func, data, join, NULL);
    if (id >=0 && id < T_MAX && _threads[id] == NULL) {
        _threads[id] = t;
    }
    
    return (t ? RC_OK : RC_NOK);
}

#endif

void threadJoin(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        //printf("threadJoin %d\n", id);
        g_thread_join(_threads[id]);
        _threads[id] = NULL;
        //printf("threadJoin %d done\n", id);
    }
}

void threadExit(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        _threads[id] = NULL;
    }
    g_thread_exit(NULL);
}

int threadExists(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        return RC_OK;
    }
    return RC_NOK;
}


#else

#include <pthread.h>
#include <time.h>

pthread_t* _threads[T_MAX] = {NULL};

void threadInit(void)
{
}

int threadNew(int id, ThreadFunction func, void* data, int param)
{
    pthread_t* tid = (pthread_t*) malloc(sizeof(pthread_t));
   
    pthread_attr_t attr;
    if (param == DETACHED) {
    	pthread_attr_init(&attr);
    	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    }

    int r;
    if ((r = pthread_create(tid, 
                            (param == JOINABLE ? NULL : &attr),        
                            (ThreadFunction) func, 
			    (void *) data )) != 0) {
    	printf("Can not run processing thread %d !\n", id);
    	free(tid);
    	return RC_NOK;
    }
	
    if (id >=0 && id < T_MAX && _threads[id] == NULL) {
        _threads[id] = tid;
    }
    
    return RC_OK;
}

void threadJoin(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        pthread_join(*(_threads[id]), NULL);
        free(_threads[id]);
        _threads[id] = NULL;
    }
}

void threadExit(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        free(_threads[id]);
        _threads[id] = NULL;
    }
    pthread_exit(NULL);
}

int threadExists(int id)
{
    if (id >=0 && id < T_MAX && _threads[id] != NULL) {
        return RC_OK;
    }
    return RC_NOK;
}

#endif

