int main()
{
    Barrier barrier1(3);
    Barrier barrier2(3);
    arrived_all = false;
    processed_all = true;
    arrived_count.store(0);
    processed_count.store(allowed_max);
    std::thread worker[50];
    for (int i = 0; i < 6; i++)
        worker[i] = std::thread(worker_thread, i, &barrier1, &barrier2);

    {
        std::lock_guard<std::mutex> lk(m);
        std::cout << "Back in main(), after initialing first thread batch " << data << std::endl;
    }


    // wait until worker dies finishes execution
    for (int i = 0; i < 6; i++)
        worker[i].join();

 //    for (int i = 5; i < 10; i++)
 //        worker[i] = std::thread(worker_thread, i);

 //    {
 //        std::lock_guard<std::mutex> lk(m);
    //     std::cout << "Back in main(), after initialing second thread batch." <<  std::endl;
    // }

 //    // wait until worker dies finishes execution
 //    for (int i = 5; i < 10; i++)
 //        worker[i].join();
    std::cout << "finished main(), data = " << data << std::endl;
}
Ejemplo n.º 2
0
void spring_time::sleep(bool forceThreadSleep)
{
	if (forceThreadSleep) {
		spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi()));
		return;
	}


	// for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest)
	if (toMicroSecsi() < (avgThreadSleepTimeMicroSecs + avgThreadYieldTimeMicroSecs * 5)) {
		const spring_time s = gettime();

		while ((gettime() - s) < *this)
			thread_yield();

		return;
	}

	// expected wakeup time
	const spring_time t0 = gettime() + *this;

	spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi()));

	const spring_time t1 = gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		// yes, it's not 100% thread correct, but it's okay when 1 of 1 million writes is dropped
		int avg = avgThreadSleepTimeMicroSecs.load();
		int newAvg = mix<float>(avg, dt.toMicroSecsf(), 0.1f);
		avgThreadSleepTimeMicroSecs.store(newAvg);
	}
}
Ejemplo n.º 3
0
    inline bool update()
    {
        if (windowId.load() == s_currentNativeWindowId.load())
            return false;

        s_currentNativeWindowMutex.lock();
        window = s_currentNativeWindow;
        windowId.store(s_currentNativeWindowId.load());
        s_currentNativeWindowMutex.unlock();
        return true;
    }
Ejemplo n.º 4
0
void stepLeft() {
	std::unique_lock<std::mutex> lock(mutex);
	for (int i = 0; i < 10; ++i) {
		std::cout << "left" << std::endl;
		isWaiting.fetch_add(1);
		if (isWaiting.load() % 2 != 0) {
			condVar.notify_one();
		}
		else {
			condVar.wait(lock);
		}
	}
}
Ejemplo n.º 5
0
static void thread_yield()
{
	const spring_time t0 = spring_time::gettime();
	this_thread::yield();
	const spring_time t1 = spring_time::gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		// yes, it's not 100% thread correct, but it's okay when 1 of 1 million writes is dropped
		int avg = avgThreadYieldTimeMicroSecs.load();
		int newAvg = mix<float>(avg, dt.toMicroSecsf(), 0.1f);
		avgThreadYieldTimeMicroSecs.store(newAvg);
	}
}
Ejemplo n.º 6
0
TEST(JobSystem, JobSystemParallelChildren) {
    v = 0;

    JobSystem js;
    js.adopt();

    struct User {
        std::atomic_int calls = {0};
        void func(JobSystem&, JobSystem::Job*) {
            v++;
            calls++;
        };
    } j;

    JobSystem::Job* root = js.createJob<User, &User::func>(nullptr, &j);
    for (int i=0 ; i<256 ; i++) {
        JobSystem::Job* job = js.createJob<User, &User::func>(root, &j);
        js.run(job);
    }
    js.runAndWait(root);

    EXPECT_EQ(257, v.load());
    EXPECT_EQ(257, j.calls);

    js.emancipate();
}
Ejemplo n.º 7
0
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
  {
    std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
    auto notifier = notifierHandles.Get(notifierHandle);
    if (!notifier) return;

    // remove from list
    if (notifier->prev) notifier->prev->next = notifier->next;
    if (notifier->next) notifier->next->prev = notifier->prev;
    if (notifiers == notifier) notifiers = notifier->next;
    notifierHandles.Free(notifierHandle);

    if (notifier->threaded) {
      NotifierThreadOwner* owner =
          static_cast<NotifierThreadOwner*>(notifier->param);
      delete owner;
    }
  }

  if (notifierRefCount.fetch_sub(1) == 1) {
    std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
    // if this was the last notifier, clean up alarm and manager
    if (notifierAlarm) {
      notifierAlarm->writeEnable(false, status);
      notifierAlarm = nullptr;
    }
    if (notifierManager) {
      notifierManager->disable(status);
      notifierManager = nullptr;
    }
    closestTrigger = UINT64_MAX;
  }
}
Ejemplo n.º 8
0
static void onSurfaceDestroyed(JNIEnv */*env*/, jobject /*object*/)
{
    s_currentNativeWindowMutex.lock();
    s_currentNativeWindow.reset();
    s_currentNativeWindowId.store(0);
    s_currentNativeWindowMutex.unlock();
}
Ejemplo n.º 9
0
Texture TextureBuilder::Build2DTexture(TextureBindpoint target, unsigned width, unsigned height, unsigned count,
                                       unsigned channels, TexturePixelFormat pixelFormat, bool useMipmaps)
{
    int current_id = id.fetch_add(1, std::memory_order_relaxed);
    Texture result;

    result.info.width = width;
    result.info.height = height;
    result.info.count = count;
    result.info.type = TextureType::Tex2D;
    result.info.target = target;
    result.info.targetPixelFormat = pixelFormat;
    result.info.channels = channels;
    result.info.name = std::string(NAME_PREFIX) + std::to_string(current_id);

    unsigned minSize = std::min(width, height);
    if (useMipmaps)
    {
        unsigned i = 0;
        while (minSize > 1)
        {
            minSize /= 2;
            i++;
        }
        result.info.mipmaps = i;
    }

    return result;
}
Ejemplo n.º 10
0
void* initializeNotifier(void (*process)(uint64_t, void*), void *param, int32_t *status)
{
	if (!process) {
		*status = NULL_PARAMETER;
		return nullptr;
	}
	if (!notifierAtexitRegistered.test_and_set())
		std::atexit(cleanupNotifierAtExit);
	if (notifierRefCount.fetch_add(1) == 0) {
		std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
		// create manager and alarm if not already created
		if (!notifierManager) {
			notifierManager = new tInterruptManager(1 << kTimerInterruptNumber, false, status);
			notifierManager->registerHandler(alarmCallback, NULL, status);
			notifierManager->enable(status);
		}
		if (!notifierAlarm) notifierAlarm = tAlarm::create(status);
	}

	std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
	// create notifier structure and add to list
	Notifier* notifier = new Notifier();
	notifier->prev = nullptr;
	notifier->next = notifiers;
	if (notifier->next) notifier->next->prev = notifier;
	notifier->param = param;
	notifier->process = process;
	notifiers = notifier;
	return notifier;
}
Ejemplo n.º 11
0
void cleanNotifier(void* notifier_pointer, int32_t *status)
{
	{
		std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
		Notifier* notifier = (Notifier*)notifier_pointer;

		// remove from list and delete
		if (notifier->prev) notifier->prev->next = notifier->next;
		if (notifier->next) notifier->next->prev = notifier->prev;
		if (notifiers == notifier) notifiers = notifier->next;
		delete notifier;
	}

	if (notifierRefCount.fetch_sub(1) == 1) {
		std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
		// if this was the last notifier, clean up alarm and manager
		if (notifierAlarm) {
			notifierAlarm->writeEnable(false, status);
			delete notifierAlarm;
			notifierAlarm = nullptr;
		}
		if (notifierManager) {
			notifierManager->disable(status);
			delete notifierManager;
			notifierManager = nullptr;
		}
		closestTrigger = UINT64_MAX;
	}
}
Ejemplo n.º 12
0
	void print(){
		if(size==0)
			printf("<empty>\n");
		for(int i = 0; i < size;i++)
			printf("%d ", arr[(head.load() + i)%capacity]);
		printf("\n");
	}
void worker_thread(int i, class Barrier& barrier1, class Barrier& barrier2)
{
    {
        // std::lock_guard<std::mutex> lk(m);
        std::lock_guard<std::mutex> lk_guard(m);
        std::cout << "Worker thread "  << i << " has arrived." << std::endl;
    }

    barrier1.wait();

    {
        std::lock_guard<std::mutex> lk_guard(m);
        std::cout << "counts changing2, processed_all: " << processed_all << ", count > max:" << (arrived_count < allowed_max) << std::endl;
        arrived_count++;
        processed_count--;
        std::cout << "counts changing3, processed: " << processed_count << ", arrived:" << arrived_count<< std::endl;
    }

    {
        std::lock_guard<std::mutex> lk_guard(m);
        if (arrived_count.load() >= allowed_max) {
            std::cout << "Enough arrived, about to open floodgate #1" << std::endl;
            arrived_all = true;
            processed_all = false;
            // for (int i = 0; i < allowed_max; i++) {
            //     cv1.notify_one();
            // }
        }
        std::cout << "about to reach 2nd barrier:" << arrived_count<< std::endl;

    }
    // std::unique_lock<std::mutex> lk1(barrier1);
    barrier2.wait();
    // cv1.wait(lk1, []{return (processed_count < allowed_max) && arrived_all;});
    {
        std::lock_guard<std::mutex> lk_guard(m);
        processed_count++;
        arrived_count--;
    }

    // critical section would go here... then increment processed_count

    // report after critical section
    {
        std::lock_guard<std::mutex> lk(m);
        std::cout << "Worker thread "  << i << " data processing completed" << std::endl;
        if (processed_count == allowed_max) {
            std::cout << "Group finished, about to open floodgate #2" << std::endl;
            processed_all = true;
            arrived_all = false;
            // for (int i = 0; i < allowed_max; i++) {
            //     cv2.notify_one();
            // }
        }
    }
}
Ejemplo n.º 14
0
    void testit(std::atomic_int& count)
    {
        std::default_random_engine generator;
        std::uniform_int_distribution<int> distribution(1, 10);
        auto sleep_time = std::bind(distribution, generator);

        std::this_thread::sleep_for(std::chrono::microseconds(sleep_time()));

        ++count;
        if(count.load() == 5) {
            g_condition.notify_one();
        }
    }
Ejemplo n.º 15
0
Order::Order(int clientAssignedId, const std::string& account, const std::string& security,
		double price, int amount, Operation operation, OrderType type) :
	m_id(gs_id.fetch_add(1)),
	m_clientAssignedId(clientAssignedId),
	m_account(account),
	m_security(security),
	m_price(price),
	m_amount(amount),
	m_operation(operation),
	m_type(type),
	m_state(State::Unsubmitted)
{

}
Ejemplo n.º 16
0
	bool add(int val){
		enqLock.lock();
		if((size+1) > capacity){
			if(addremdbg) printf("af %d\n", val);
			enqLock.unlock();
			return false;
		}
		if(addremdbg) printf("ap %d\n", val);
		arr[tail] = val;
		tail = (tail.load()+1)%capacity;
		size++;
		enqLock.unlock();
		return true;
	}
Ejemplo n.º 17
0
inline void thread_pool::execute(delegate_type e)
{
  if (fc_.fetch_sub(1, ::std::memory_order_relaxed) <= 0)
  {
    spawn_thread();
  }
  // else do nothing

  {
    ::std::lock_guard<decltype(cm_)> l(cm_);

    delegates_.emplace_back(::std::move(e));
  }

  cv_.notify_one();
}
Ejemplo n.º 18
0
int main () {
  using namespace shmdata;

  {
    // direct access writer with one reader
    Writer w("/tmp/check-stress",
             sizeof(Frame),
             "application/x-check-shmdata",
             &logger);
    assert(w);
    // init
    {
      Frame frame;
      assert(w.copy_to_shm(&frame, sizeof(Frame)));
    }
    Reader r("/tmp/check-stress",
             [](void *data, size_t size){
               // auto frame = static_cast<Frame *>(data);
               // std::cout << "(0) new data for client "
               //           << frame->count
               //           << " (size " << size << ")"
               //           << std::endl;
             },
             nullptr,
             nullptr,
             &logger);
    std::cout << "one reader" << std::endl;
    assert(r);
    auto reader_handle = std::async(std::launch::async, reader);
    while (1 != done.load()) {
      //  the following is locking the shared memory for writing
      auto access = w.get_one_write_access();
      assert(access);
      access->notify_clients(sizeof(Frame));
      auto frame = static_cast<Frame *>(access->get_mem());
      frame->count++;
    }
    assert(reader_handle.get());
  }
  std::this_thread::sleep_for (std::chrono::milliseconds(1000));
  std::cout << "fin" << std::endl;
  return 0;
}
Ejemplo n.º 19
0
int main(int argc, char** argv)
{
    if (argc != 8)
    {
        printf("%s sAddr1 sAddr2 sAddr3 iChannelNum iWorkerNumPerChannel iCountPerWorker iEntityNum\n",
                argv[0]);
        exit(-1);
    }

    std::vector<std::string> vecIPList;
    for (int i = 1; i <= 3; ++i)
        vecIPList.push_back(argv[i]);

    int iChannelNum = atoi(argv[4]);
    int iWorkerNumPerChannel = atoi(argv[5]);
    int iCountPerWorker = atoi(argv[6]);
    uint64_t iEntityNum = atoi(argv[7]);

    clsUUIDGenerator::GetInstance()->Init();

    for (int i = 0; i < iChannelNum; ++i)
    {
        std::shared_ptr<clsClient> poClient(new clsClient(&vecIPList));
        for (int j = 0; j < iWorkerNumPerChannel; ++j)
        {
            clsRWStressTester* poTester = new clsRWStressTester(poClient, iCountPerWorker, iEntityNum);
            poTester->Start();
        }
    }

    while (s_iStopCnt.load() == 0)
    {
        sleep(1);
        s_oStat.Print();
    }

    printf("Fail %lu\n", s_iFailCnt.load());

    return 0;
}
Ejemplo n.º 20
0
void
handle_subscribe_multiple (int argc, const char *argv[])
{
    uint32_t      count = atoi(argv[1]);
    pthread_t     *tid;
    CommandContext context(argc, argv, NULL);

    // Create N threads
    tid = new pthread_t[count];
    for (int i = 0; i < count; i++) {
        pthread_create(&tid[i], NULL, proc, (void *) &context);
    }

    // Give few mins to subscribe all
    sleep(5);
    // Reset id
    some_id.store(0);

    // Wait for them to finish
    for (int i = 0; i < count; i++) {
        pthread_join(tid[i], NULL);
    }
}
Ejemplo n.º 21
0
HAL_NotifierHandle HAL_InitializeNotifier(HAL_NotifierProcessFunction process,
                                          void* param, int32_t* status) {
  if (!process) {
    *status = NULL_PARAMETER;
    return 0;
  }
  if (!notifierAtexitRegistered.test_and_set())
    std::atexit(cleanupNotifierAtExit);
  if (notifierRefCount.fetch_add(1) == 0) {
    std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
    // create manager and alarm if not already created
    if (!notifierManager) {
      notifierManager = std::make_unique<tInterruptManager>(
          1 << kTimerInterruptNumber, false, status);
      notifierManager->registerHandler(alarmCallback, nullptr, status);
      notifierManager->enable(status);
    }
    if (!notifierAlarm) notifierAlarm.reset(tAlarm::create(status));
  }

  std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
  std::shared_ptr<Notifier> notifier = std::make_shared<Notifier>();
  HAL_NotifierHandle handle = notifierHandles.Allocate(notifier);
  if (handle == HAL_kInvalidHandle) {
    *status = HAL_HANDLE_ERROR;
    return HAL_kInvalidHandle;
  }
  // create notifier structure and add to list
  notifier->next = notifiers;
  if (notifier->next) notifier->next->prev = notifier;
  notifier->param = param;
  notifier->process = process;
  notifier->handle = handle;
  notifier->threaded = false;
  notifiers = notifier;
  return handle;
}
Ejemplo n.º 22
0
bool reader(){
  { // creating one reader
    std::this_thread::sleep_for (std::chrono::milliseconds(10));
    Reader r("/tmp/check-stress",
             [](void *data, size_t size){
               // auto frame = static_cast<Frame *>(data);
               // std::cout << "(one reader) new data for client "
               //           << frame->count
               //           << " (size " << size << ")"
               //           << std::endl;
             },
             nullptr,
             nullptr,
             &logger);
    assert(r);
    std::cout << "one more reader" << std::endl;
    std::this_thread::sleep_for (std::chrono::milliseconds(1000));
  }
  std::cout << "one less reader" << std::endl;
  { // creating five readers
    std::this_thread::sleep_for (std::chrono::milliseconds(10));
    Reader r1("/tmp/check-stress",
              [](void *data, size_t size){
                // auto frame = static_cast<Frame *>(data);
                // std::cout << "(1) new data for client "
                //           << frame->count
                //           << " (size " << size << ")"
                //           << std::endl;
              },
             nullptr,
             nullptr,
              &logger);
    assert(r1);
    Reader r2("/tmp/check-stress",
              [](void *data, size_t size){
                // auto frame = static_cast<Frame *>(data);
                // std::cout << "(2) new data for client "
                //           << frame->count
                //           << " (size " << size << ")"
                //           << std::endl;
              },
             nullptr,
             nullptr,
             &logger);
    assert(r2);
    Reader r3("/tmp/check-stress",
              [](void *data, size_t size){
                // auto frame = static_cast<Frame *>(data);
                // std::cout << "(3) new data for client "
                //           << frame->count
                //           << " (size " << size << ")"
                //           << std::endl;
              },
             nullptr,
             nullptr,
             &logger);
    assert(r3);
    Reader r4("/tmp/check-stress",
              [](void *data, size_t size){
                // auto frame = static_cast<Frame *>(data);
                // std::cout << "(4) new data for client "
                //           << frame->count
                //           << " (size " << size << ")"
                //           << std::endl;
              },
              nullptr,
              nullptr,
              &logger);
    assert(r4);
    Reader r5("/tmp/check-stress",
              [](void *data, size_t size){
                // auto frame = static_cast<Frame *>(data);
                // std::cout << "(5) new data for client "
                //           << frame->count
                //          << " (size " << size << ")"
                //           << std::endl;
              },
              nullptr,
              nullptr,
              &logger);
    assert(r5);
    std::cout << "five more reader" << std::endl;
    std::this_thread::sleep_for (std::chrono::milliseconds(1000));
  }
  std::this_thread::sleep_for (std::chrono::milliseconds(100));
  done.store(1);
  std::cout << "done set to 1" << std::endl;
  return true;
}
Ejemplo n.º 23
0
 // ------------------------------------------------------------------------
 void increaseGLCommandFunctionCount(int count)
                               { m_gl_cmd_function_count.fetch_add(count); }
Ejemplo n.º 24
0
static void *doit(int id, Config &conf)
{
    
    FCGX_Request request;
	
    if(FCGX_InitRequest(&request, socketId.load(), 0) != 0)
    {
        //ошибка при инициализации структуры запроса
        printf("Can not init request\n");
        return NULL;
    }

	Router router(&request, &conf);
	
	router.addHandler("OPTIONS",	"/users/login", 		&OptUsersLogin);
	router.addHandler("GET",		"/users/login", 		&UsersInfo);
	router.addHandler("POST",		"/users/login", 		&PostUsersLogin);
	
	router.addHandler("OPTIONS",	"/users/add", 			&OptUsersAdd);
	router.addHandler("POST",		"/users/add", 			&PostUsersAdd);
	
	router.addHandler("OPTIONS",	".*", 					&OptDirs);
	router.addHandler("OPTIONS",	"/dirs/(?<id>\\d+)",	&OptDirs);
	
	router.addHandler("POST",		"/dirs", 				&PostCreateDir);
	router.addHandler("GET",		"/dirs/(\\d+)",			&GetDir);
	router.addHandler("DELETE",		"/dirs/(\\d+)",			&DelDir);
	
	router.addHandler("POST",		"/files/(\\d+)/(.+)",	&PutFile);
	router.addHandler("GET",		"/files/(\\d+)",		&GetFile);
	router.addHandler("DELETE",		"/files/(\\d+)",		&DelFile);


    for(;;)
    {
        static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;

        pthread_mutex_lock(&accept_mutex);
        int rc = FCGX_Accept_r(&request);
		
		pthread_mutex_unlock(&accept_mutex);
        
        if(rc < 0)
        {
            //ошибка при получении запроса
            printf("Can not accept new request\n");
            break;
        }

	   	std::streambuf * cin_streambuf  = std::cin.rdbuf();
	    std::streambuf * cout_streambuf = std::cout.rdbuf();
	    std::streambuf * cerr_streambuf = std::cerr.rdbuf();    


        fcgi_streambuf cin_fcgi_streambuf(request.in);
        fcgi_streambuf cout_fcgi_streambuf(request.out);
        fcgi_streambuf cerr_fcgi_streambuf(request.err);

        std::cin.rdbuf(&cin_fcgi_streambuf);
        std::cout.rdbuf(&cout_fcgi_streambuf);
        std::cerr.rdbuf(&cerr_fcgi_streambuf);
		try
		{	
			router.Run();
		}
		catch (Error &e)
		{
			router.SetStatus(e.http_code());
			router.AddHeader("Content-Type", "application/json; charset=utf-8");
			router.AddContent(e.what());
			router.AcceptContent();
		}
		catch (std::exception &e)
		{
			std::cerr << e.what();
			router.SetStatus(Httpstatus::InternalServerError);
			router.AddHeader("Content-Type", "text/plain; charset=utf-8");
			router.AddContent(e.what());
			router.AcceptContent();
		}
		
		FCGX_Finish_r(&request);
		
        //завершающие действия - запись статистики, логгирование ошибок и т.п.

		router.Cleanup();


	    std::cin.rdbuf(cin_streambuf);
	    std::cout.rdbuf(cout_streambuf);
	    std::cerr.rdbuf(cerr_streambuf);

    }


    return NULL;
}
Ejemplo n.º 25
0
namespace glws {
static char TAG[]="apitrace";

static JavaVM *s_javaVM = nullptr;
static jobject s_activityObject = nullptr;
static std::mutex s_activityObjectMutex;

static jmethodID s_setSurfaceSizeMethodID = nullptr;

static jfieldID s_descriptor = nullptr;

typedef std::shared_ptr<ANativeWindow> AndroidWindow;
static AndroidWindow s_currentNativeWindow;
static std::atomic_int s_currentNativeWindowId(0);
static std::mutex s_currentNativeWindowMutex;

static int s_stdout_fd = -1;
static int s_stderr_fd = -1;
static std::mutex s_stateMutex;
static std::condition_variable s_stateWait;

static EGLDisplay eglDisplay = EGL_NO_DISPLAY;
static char const *eglExtensions = NULL;
static bool has_EGL_KHR_create_context = false;
struct ResourceTracker;

static std::mutex s_resourcesMutex;
static std::vector<ResourceTracker*> s_resources;

class FdWriter : public std::streambuf
{
public:
    FdWriter(int fd)
    {
        m_fd = fd;
        int opts = fcntl(m_fd, F_GETFL);
        opts = opts & (~O_NONBLOCK);
        fcntl(m_fd, F_SETFL, opts);
    }

    // basic_streambuf interface
protected:
    std::streamsize xsputn(const char_type *__s, std::streamsize __n)
    {
        std::streamsize ret = 0;
        while( __n ) {
            ssize_t written = write(m_fd, __s, __n);
            if (written > 0) {
                __n -= written;
                __s += written;
                ret += written;
            } else {
                switch (errno) {
                case EBADF:
                case EINVAL:
                case EPIPE:
                    std::exit(1);
                    break;
                }
            }
        }
        return ret;
    }

    int_type overflow(int_type __c)
    {
        return xsputn(reinterpret_cast<const char_type *>(&__c), 1) == 1 ? __c : traits_type::eof();
    }

private:
    int m_fd = -1;
};

static EGLenum
translateAPI(glprofile::Profile profile)
{
    switch (profile.api) {
    case glprofile::API_GL:
        return EGL_OPENGL_API;
    case glprofile::API_GLES:
        return EGL_OPENGL_ES_API;
    default:
        assert(0);
        return EGL_NONE;
    }
}


/* Must be called before
 *
 * - eglCreateContext
 * - eglGetCurrentContext
 * - eglGetCurrentDisplay
 * - eglGetCurrentSurface
 * - eglMakeCurrent (when its ctx parameter is EGL_NO_CONTEXT ),
 * - eglWaitClient
 * - eglWaitNative
 */
static void
bindAPI(EGLenum api)
{
    if (eglBindAPI(api) != EGL_TRUE) {
        std::cerr << "error: eglBindAPI failed\n";
        exit(1);
    }
}

struct EglVisual : public Visual
{
    EglVisual(Profile prof) : Visual(prof) {}
    EGLConfig config = 0;
    EGLint format = -1;
};

struct ResourceTracker
{
    ResourceTracker()
    {
        s_resourcesMutex.lock();
        s_resources.push_back(this);
        s_resourcesMutex.unlock();
    }

    virtual ~ResourceTracker()
    {
        s_resourcesMutex.lock();
        s_resources.erase(std::find(s_resources.begin(), s_resources.end(), this));
        s_resourcesMutex.unlock();
    }
};

class EglDrawable : public Drawable, private ResourceTracker
{
public:
    EglDrawable(const Visual *vis, int w, int h, bool pbuffer) :
        Drawable(vis, w, h, pbuffer),
        api(EGL_OPENGL_ES_API),
        windowId(0)
    {
        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
        const EglVisual * eglVisual = static_cast<const EglVisual *>(visual);
        update();
        ANativeWindow_setBuffersGeometry(window.get(), 0, 0, eglVisual->format);
        surface = eglCreateWindowSurface(eglDisplay, eglVisual->config, window.get(), NULL);
    }

    ~EglDrawable()
    {
        eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        eglDestroySurface(eglDisplay, surface);
        eglWaitClient();
        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
    }

    void recreate(void)
    {
        EGLContext currentContext = eglGetCurrentContext();
        EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
        EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
        bool rebindDrawSurface = currentDrawSurface == surface;
        bool rebindReadSurface = currentReadSurface == surface;

        if (rebindDrawSurface || rebindReadSurface) {
            eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            eglDestroySurface(eglDisplay, surface);
        }

        const EglVisual * eglVisual = static_cast<const EglVisual *>(visual);
        ANativeWindow_setBuffersGeometry(window.get(), 0, 0, eglVisual->format);
        surface = eglCreateWindowSurface(eglDisplay, eglVisual->config, (EGLNativeWindowType)window.get(), NULL);

        if (rebindDrawSurface || rebindReadSurface)
            eglMakeCurrent(eglDisplay, surface, surface, currentContext);
    }

    void
    resize(int w, int h) {
        if (w == width && h == height) {
            return;
        }
        eglWaitClient();
        Drawable::resize(w, h);
        resizeSurface(w, h);
    }

    void show(void) {
        if (visible) {
            return;
        }
        eglWaitClient();
        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
        Drawable::show();
    }

    void swapBuffers(void) {
        if (update())
            recreate();
        bindAPI(api);
        eglSwapBuffers(eglDisplay, surface);
    }

private:
    inline bool update()
    {
        if (windowId.load() == s_currentNativeWindowId.load())
            return false;

        s_currentNativeWindowMutex.lock();
        window = s_currentNativeWindow;
        windowId.store(s_currentNativeWindowId.load());
        s_currentNativeWindowMutex.unlock();
        return true;
    }

    void resizeSurface(int w, int h)
    {
        JNIEnv *env = nullptr;
        if (JNI_OK != s_javaVM->AttachCurrentThread(&env, nullptr)) {
            __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
            std::exit(1);
        }
        s_activityObjectMutex.lock();
        env->CallVoidMethod(s_activityObject, s_setSurfaceSizeMethodID, w, h);
        if (env->ExceptionCheck()) {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
        s_activityObjectMutex.unlock();
        s_javaVM->DetachCurrentThread();
    }

public:
    EGLSurface surface;
    EGLenum api;

private:
    AndroidWindow window;
    std::atomic_int windowId;
};


class EglContext : public Context, private ResourceTracker
{
public:
    EGLContext context;

    EglContext(const Visual *vis, EGLContext ctx) :
        Context(vis),
        context(ctx)
    {}

    ~EglContext() {
        eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        eglDestroyContext(eglDisplay, context);
    }
};

void
init(void) {
    eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (eglDisplay == EGL_NO_DISPLAY) {
        std::cerr << "error: unable to get EGL display\n";
        exit(1);
    }

    EGLint major, minor;
    if (!eglInitialize(eglDisplay, &major, &minor)) {
        std::cerr << "error: unable to initialize EGL display\n";
        exit(1);
    }

    eglExtensions = eglQueryString(eglDisplay, EGL_EXTENSIONS);
    has_EGL_KHR_create_context = checkExtension("EGL_KHR_create_context", eglExtensions);
}

void
cleanup(void) {
    while (!s_resources.empty()) {
        delete *s_resources.rbegin();
    }

    if (eglDisplay != EGL_NO_DISPLAY) {
        eglTerminate(eglDisplay);
    }
    eglDisplay = EGL_NO_DISPLAY;
    eglExtensions = nullptr;
    has_EGL_KHR_create_context = false;
    s_stateMutex.lock();
    close(s_stdout_fd);
    close(s_stderr_fd);
    s_stdout_fd = -1;
    s_stderr_fd = -1;
    s_stateMutex.unlock();
}

Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
    EGLint api_bits;
    if (profile.api == glprofile::API_GL) {
        api_bits = EGL_OPENGL_BIT;
        if (profile.core && !has_EGL_KHR_create_context) {
            return NULL;
        }
    } else if (profile.api == glprofile::API_GLES) {
        switch (profile.major) {
        case 1:
            api_bits = EGL_OPENGL_ES_BIT;
            break;
        case 3:
            if (has_EGL_KHR_create_context) {
                api_bits = EGL_OPENGL_ES3_BIT;
                break;
            }
            /* fall-through */
        case 2:
            api_bits = EGL_OPENGL_ES2_BIT;
            break;
        default:
            return NULL;
        }
    } else {
        assert(0);
        return NULL;
    }

    Attributes<EGLint> attribs;
    attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
    attribs.add(EGL_RED_SIZE, 1);
    attribs.add(EGL_GREEN_SIZE, 1);
    attribs.add(EGL_BLUE_SIZE, 1);
    attribs.add(EGL_ALPHA_SIZE, 1);
    attribs.add(EGL_DEPTH_SIZE, 1);
    attribs.add(EGL_STENCIL_SIZE, 1);
    attribs.add(EGL_RENDERABLE_TYPE, api_bits);
    attribs.end(EGL_NONE);

    EGLint num_configs = 0;
    if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) ||
        num_configs <= 0) {
        return NULL;
    }

    std::vector<EGLConfig> configs(num_configs);
    if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs,  &num_configs) ||
        num_configs <= 0) {
        return NULL;
    }

    // We can't tell what other APIs the trace will use afterwards, therefore
    // try to pick a config which supports the widest set of APIs.
    int bestScore = -1;
    EGLConfig config = configs[0];
    for (EGLint i = 0; i < num_configs; ++i) {
        EGLint renderable_type = EGL_NONE;
        eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type);
        int score = 0;
        assert(renderable_type & api_bits);
        renderable_type &= ~api_bits;
        if (renderable_type & EGL_OPENGL_ES2_BIT) {
            score += 1 << 4;
        }
        if (renderable_type & EGL_OPENGL_ES3_BIT) {
            score += 1 << 3;
        }
        if (renderable_type & EGL_OPENGL_ES_BIT) {
            score += 1 << 2;
        }
        if (renderable_type & EGL_OPENGL_BIT) {
            score += 1 << 1;
        }
        if (score > bestScore) {
            config = configs[i];
            bestScore = score;
        }
    }
    assert(bestScore >= 0);

    EGLint visual_id = -1;
    if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) {
        assert(0);
        return NULL;
    }
    assert(visual_id != -1);

    EglVisual *visual = new EglVisual(profile);
    visual->config = config;
    visual->format = visual_id;

    return visual;
}

Drawable *
createDrawable(const Visual *visual, int width, int height, bool pbuffer)
{
    return new EglDrawable(visual, width, height, pbuffer);
}


Context *
createContext(const Visual *_visual, Context *shareContext, bool debug)
{
    Profile profile = _visual->profile;
    const EglVisual *visual = static_cast<const EglVisual *>(_visual);
    EGLContext share_context = EGL_NO_CONTEXT;
    EGLContext context;
    Attributes<EGLint> attribs;

    if (shareContext) {
        share_context = static_cast<EglContext*>(shareContext)->context;
    }

    int contextFlags = 0;
    if (profile.api == glprofile::API_GL) {
        if (has_EGL_KHR_create_context) {
            attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
            attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
            int profileMask = profile.core ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
            attribs.add(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, profileMask);
            if (profile.forwardCompatible) {
                contextFlags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
            }
        } else if (profile.versionGreaterOrEqual(3, 2)) {
            std::cerr << "error: EGL_KHR_create_context not supported\n";
            return NULL;
        }
    } else if (profile.api == glprofile::API_GLES) {
        if (has_EGL_KHR_create_context) {
            attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
            attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
        } else {
            attribs.add(EGL_CONTEXT_CLIENT_VERSION, profile.major);
        }
    } else {
        assert(0);
        return NULL;
    }

    if (debug) {
        contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
    }
    if (contextFlags && has_EGL_KHR_create_context) {
        attribs.add(EGL_CONTEXT_FLAGS_KHR, contextFlags);
    }
    attribs.end(EGL_NONE);

    EGLenum api = translateAPI(profile);
    bindAPI(api);

    context = eglCreateContext(eglDisplay, visual->config, share_context, attribs);
    if (!context) {
        if (debug) {
            // XXX: Mesa has problems with EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
            // with OpenGL ES contexts, so retry without it
            return createContext(_visual, shareContext, false);
        }
        return NULL;
    }

    return new EglContext(visual, context);
}

bool
makeCurrentInternal(Drawable *drawable, Context *context)
{
    if (!drawable || !context) {
        return eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    } else {
        EglDrawable *eglDrawable = static_cast<EglDrawable *>(drawable);
        EglContext *eglContext = static_cast<EglContext *>(context);
        EGLBoolean ok;

        EGLenum api = translateAPI(eglContext->profile);
        bindAPI(api);

        ok = eglMakeCurrent(eglDisplay, eglDrawable->surface,
                            eglDrawable->surface, eglContext->context);

        if (ok) {
            eglDrawable->api = api;
        }

        return ok;
    }
}

bool processEvents(void)
{
    return false;
}

static void readParamsAndStartTrace()
{
    std::string paramsLine;
    char buff[4096];
    while (true) {
        ssize_t sz = read(s_stdout_fd, buff, 4095);
        if (sz < 0) {
            cleanup();
            return ;
        }
        buff[sz] = '\0';
        paramsLine += buff;
        if (paramsLine.find('\n') > 0)
            break;
    }
    std::regex word_regex("(\"[^\"]*\")|([^\\s]+)");
    auto words_begin =
        std::sregex_iterator(paramsLine.begin(), paramsLine.end(), word_regex);
    auto words_end = std::sregex_iterator();
    std::vector<std::string> paramsVector;
    std::vector<char *> params;
    params.push_back(TAG);
    for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
        paramsVector.push_back(i->str());
        params.push_back(const_cast<char*>(paramsVector.back().c_str()));
    }

    {
        std::unique_lock<std::mutex> lock(s_stateMutex);
        __android_log_print(ANDROID_LOG_DEBUG, TAG, "Wait for stderr socket");
        s_stateWait.wait(lock, []{return s_stderr_fd != -1; });
    }
    __android_log_print(ANDROID_LOG_DEBUG, TAG, "Start retrace");
    optind = 1;
    optreset = 1;
    main(params.size(), &params[0]);
    cleanup();

    // Remove "std::exit" after apitrace will cleanup its static variables.
    std::exit(0); // goodbye cruel world !
}

static inline int getFd(JNIEnv* env, jobject obj)
{
    return env->GetIntField(obj, s_descriptor);
}

static bool setFd(std::ostream &stream, int *state_fd, int fd)
{
    std::lock_guard<std::mutex> lock(s_stateMutex);
    if (*state_fd != -1)
        return false;
    *state_fd = fd;
    delete dynamic_cast<FdWriter*>(stream.rdbuf(new FdWriter(fd)));
    return true;
}

static jboolean setStdoutFileDescriptor(JNIEnv *env, jobject /*object*/, jobject fd)
{
    bool res = setFd(std::cout, &s_stdout_fd, getFd(env, fd));
    if (res)
        std::async(std::launch::async, glws::readParamsAndStartTrace);
    return res;
}

static jboolean setStderrFileDescriptor(JNIEnv *env, jobject /*object*/, jobject fd)
{
    bool res = setFd(std::cerr, &s_stderr_fd, getFd(env, fd));
    if (res)
        s_stateWait.notify_one();
    return res;
}

static void onActivityCreated(JNIEnv *env, jobject /*object*/, jobject activity)
{
    s_activityObjectMutex.lock();
    s_activityObject = env->NewGlobalRef(activity);
    s_activityObjectMutex.unlock();
}

static void onSurfaceCreated(JNIEnv *env, jobject /*object*/, jobject surface)
{
    s_currentNativeWindowMutex.lock();
    s_currentNativeWindow = AndroidWindow(ANativeWindow_fromSurface(env, surface), [](ANativeWindow *w) { ANativeWindow_release(w); });
    ++s_currentNativeWindowId;
    s_currentNativeWindowMutex.unlock();
}

static void onSurfaceChanged(JNIEnv *env, jobject /*object*/, jobject surface, int /*format*/, int /*width*/, int /*height*/)
{
    s_currentNativeWindowMutex.lock();
    s_currentNativeWindow = AndroidWindow(ANativeWindow_fromSurface(env, surface), [](ANativeWindow *w) { ANativeWindow_release(w); });
    ++s_currentNativeWindowId;
    s_currentNativeWindowMutex.unlock();
}

static void onSurfaceRedrawNeeded(JNIEnv */*env*/, jobject /*object*/, jobject /*surface*/)
{
}

static void onSurfaceDestroyed(JNIEnv */*env*/, jobject /*object*/)
{
    s_currentNativeWindowMutex.lock();
    s_currentNativeWindow.reset();
    s_currentNativeWindowId.store(0);
    s_currentNativeWindowMutex.unlock();
}

static void onActivityDestroyed(JNIEnv *env, jobject /*object*/)
{
    s_activityObjectMutex.lock();
    env->DeleteGlobalRef(s_activityObject);
    s_activityObject = nullptr;
    s_activityObjectMutex.unlock();
}

static JNINativeMethod methods[] = {
    {"setStdoutFileDescriptor", "(Ljava/io/FileDescriptor;)Z", (void *)setStdoutFileDescriptor},
    {"setStderrFileDescriptor", "(Ljava/io/FileDescriptor;)Z", (void *)setStderrFileDescriptor},
    {"onActivityCreatedNative", "(Lapitrace/github/io/eglretrace/RetraceActivity;)V", (void *)onActivityCreated},
    {"onSurfaceCreatedNative", "(Landroid/view/Surface;)V", (void *)onSurfaceCreated},
    {"onSurfaceChangedNative", "(Landroid/view/Surface;III)V", (void *)onSurfaceChanged},
    {"onSurfaceRedrawNeededNative", "(Landroid/view/Surface;)V", (void *)onSurfaceRedrawNeeded},
    {"onSurfaceDestroyedNative", "()V", (void *)onSurfaceDestroyed},
    {"onActivityDestroyedNative", "()V", (void *)onActivityDestroyed}
};

} /* namespace glws */
Ejemplo n.º 26
0
int main(int argc, char **argv)
{
    
    int i;
    
    std::ostringstream conffile;
    conffile << SYSCONFDIR << "/restfsd.ini";
	Config conf(conffile.str());
	
	const int THREAD_COUNT = conf.GetInteger("main","threads",2);
    std::thread *id = new std::thread[THREAD_COUNT];


	FCGX_Init();

	socketId.store( FCGX_OpenSocket(conf.get("main","listen").c_str(), 20) );
	if(socketId < 0)
	{
		printf("Socket isn't opened\n");
		return 1;
	}
        
	//~ int pid;	
	//~ pid = fork();
	//~ if (pid == -1)
	//~ {
		//~ printf("Error: Start Daemon failed (%s)\n", strerror(errno));
		//~ return -1;
	//~ }
	//~ else if (!pid)
	//~ {
		//~ umask(0);
		//~ setsid();
		//~ //chdir("/home/sokol");
		for(i = 0; i < THREAD_COUNT; i++)
		{
			id[i] = std::thread( doit, i, std::ref(conf) );
		}
		//~ sleep(1);
		//~ std::cout << "main1 " <<  conf.get("test","test") << std::endl;
		//~ for(i = 0; i < THREAD_COUNT; i++)
		//~ {
			//~ id[i].join();
			//~ id[i].detach();
		//~ }
        
        //~ while(true) {
			//~ //std::cout << "while" << std::endl;
	        //~ for(i = 0; i < THREAD_COUNT; i++)
	        //~ {
	            //~ id[i].join();
	            //~ std::cout << "thread[" << i << "].get_id: " << id[i].get_id() << std::endl;
	            //~ if (id[i].joinable())
				//~ {
					//~ id[i].join();
				//~ } else
				//~ {
					//~ std::cout << "thread[" << i << "]: starting" << std::endl;
					//~ id[i] = std::thread( doit, i, std::ref(conf) );
				//~ }
	        //~ }
			//~ //sleep(1);
		//~ }
		//~ close(STDIN_FILENO);
		//~ close(STDOUT_FILENO);
		//~ close(STDERR_FILENO);

		for(i = 0; i < THREAD_COUNT; i++)
		{
			id[i].join();
		}
		
        //~ std::cout << "main2" << conf.get("test","test") << std::endl;
		return 0;

	//~ } else
	//~ {
		//~ printf("Start Daemon pid=(%d)\n", pid);
		//~ return 0;
	//~ }
}