blob: 9d7633546cc35628a6d9a7d70b26afaeee55ac35 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_
#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <thread>
extern "C" {
enum {
ANDROID_PRIORITY_FOREGROUND = -2,
};
}
namespace android {
enum {
PRIORITY_DEFAULT = 0,
};
// DO NOT USE FOR NEW CODE - please use std::thread, or something else. This
// shim is only to allow some android code to compile and run on Fuchsia.
// Intentionally do not support repeated calls to run(), even if the android
// implementation may be trying to support that (unclear). In this
// implementation an instance of this class can only correspond to up to one
// underlying thread lifetime, by design.
//
// The proper way to wait until the thread is really actually fully done running
// is to call requestExitAndWait(), or requestExit() and ~Thread. FWIW, until
// that's done, it's not safe to do something that could change running code
// such as un-load of a shared library that contains an instance of the code of
// this class, since the tail end of _threadLoop() could still be running on the
// thread. We expect libc++.so to remain loaded, so we don't need to analyze
// whether std::thread code itself is robust to code unloading. We don't
// currently expect to un-load any code (including the code of this class), but
// this class should be reasonably ready for code unloading should it be added
// at some point.
// The virtual inheritance is probably not currently important for the current
// Fuchsia usage, but is here to maximize compatibility for now.
class Thread : virtual public RefBase {
public:
// This Thread shim on Fuchsia only supports can_call_java == false, else
// abort().
explicit Thread(bool can_call_java = true);
virtual ~Thread();
virtual status_t run(const char* thread_name,
int32_t thread_priority = PRIORITY_DEFAULT,
size_t stack_size = 0);
virtual void requestExit();
status_t requestExitAndWait();
protected:
// This would be private or completely removed in the Fuchsia implementation
// except for ALooper using it to stash the thread ID.
virtual status_t readyToRun();
private:
virtual bool threadLoop() = 0;
void _threadLoop();
bool isExitRequested() const;
void joinCommon();
mutable std::mutex lock_;
bool is_run_called_ = false;
std::unique_ptr<std::thread> thread_;
// The status of starting the thread, not anything more.
status_t start_status_ = NO_ERROR;
bool is_exit_requested_ = false;
bool is_joiner_selected_ = false;
bool is_joined_ = false;
std::condition_variable joined_condition_;
sp<Thread> hold_self_;
};
} // namespace android
#endif // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_