1f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Copyright 2013 Google Inc. All Rights Reserved.
2f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//
3f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Use of this source code is governed by a BSD-style license
4f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// that can be found in the COPYING file in the root of the source
5f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// tree. An additional intellectual property rights grant can be found
6f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// in the file PATENTS. All contributing project authors may
7f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// be found in the AUTHORS file in the root of the source tree.
8f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// -----------------------------------------------------------------------------
9f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//
10f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Multi-threaded worker
11f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//
12f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Original source:
13f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//  http://git.chromium.org/webm/libwebp.git
14f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//  100644 blob 13a61a4c84194c3374080cbf03d881d3cd6af40d  src/utils/thread.h
15f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
16f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
17f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#ifndef VP9_DECODER_VP9_THREAD_H_
18f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#define VP9_DECODER_VP9_THREAD_H_
19f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
205ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include "./vpx_config.h"
21f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
22f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#if defined(__cplusplus) || defined(c_plusplus)
23f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangextern "C" {
24f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#endif
25f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
26f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#if CONFIG_MULTITHREAD
27f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
28f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#if defined(_WIN32)
29f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
305ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include <windows.h>  // NOLINT
31f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef HANDLE pthread_t;
32f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef CRITICAL_SECTION pthread_mutex_t;
33f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef struct {
34f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  HANDLE waiting_sem_;
35f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  HANDLE received_sem_;
36f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  HANDLE signal_event_;
37f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang} pthread_cond_t;
38f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
39f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#else
40f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#include <pthread.h> // NOLINT
42f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
43f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#endif    /* _WIN32 */
44f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#endif    /* CONFIG_MULTITHREAD */
45f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
46f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// State of the worker thread object
47f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef enum {
48f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  NOT_OK = 0,   // object is unusable
49f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  OK,           // ready to work
50f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  WORK          // busy finishing the current task
51f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang} VP9WorkerStatus;
52f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
53f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Function to be called by the worker thread. Takes two opaque pointers as
54f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// arguments (data1 and data2), and should return false in case of error.
55f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef int (*VP9WorkerHook)(void*, void*);
56f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
57f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Synchronize object used to launch job in the worker thread
58f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangtypedef struct {
59f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#if CONFIG_MULTITHREAD
60f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  pthread_mutex_t mutex_;
61f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  pthread_cond_t  condition_;
62f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  pthread_t       thread_;
63f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#endif
64f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  VP9WorkerStatus status_;
65f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  VP9WorkerHook hook;     // hook to call
66f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  void* data1;            // first argument passed to 'hook'
67f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  void* data2;            // second argument passed to 'hook'
68f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  int had_error;          // return value of the last call to 'hook'
69f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang} VP9Worker;
70f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
71f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Must be called first, before any other method.
72f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangvoid vp9_worker_init(VP9Worker* const worker);
73f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Must be called to initialize the object and spawn the thread. Re-entrant.
74f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Will potentially launch the thread. Returns false in case of error.
75f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangint vp9_worker_reset(VP9Worker* const worker);
76f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Makes sure the previous work is finished. Returns true if worker->had_error
77f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// was not set and no error condition was triggered by the working thread.
78f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangint vp9_worker_sync(VP9Worker* const worker);
79f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Triggers the thread to call hook() with data1 and data2 argument. These
80f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// hook/data1/data2 can be changed at any time before calling this function,
81f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// but not be changed afterward until the next call to vp9_worker_sync().
82f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangvoid vp9_worker_launch(VP9Worker* const worker);
835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// This function is similar to vp9_worker_launch() except that it calls the
845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// hook directly instead of using a thread. Convenient to bypass the thread
855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// mechanism while still using the VP9Worker structs. vp9_worker_sync() must
865ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// still be called afterward (for error reporting).
875ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangvoid vp9_worker_execute(VP9Worker* const worker);
88f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// Kill the thread and terminate the object. To use the object again, one
89f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang// must call vp9_worker_reset() again.
90f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangvoid vp9_worker_end(VP9Worker* const worker);
91f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
92f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang//------------------------------------------------------------------------------
93f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
94f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#if defined(__cplusplus) || defined(c_plusplus)
95f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang}    // extern "C"
96f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang#endif
97f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
985ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#endif  // VP9_DECODER_VP9_THREAD_H_
99