Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Unified Diff: native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc

Issue 14607005: [NaCl SDK] Cleanup examples. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: feedback Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
diff --git a/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
index bada6105c5cab2a52d5de67ddb3bcbb02fe39410..6080b0377bb850241c1953d3f9761a795025067e 100644
--- a/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
+++ b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
@@ -2,16 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <math.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
-#include <cassert>
-#include <cmath>
-#include <cstring>
+
#include <string>
-#include "ppapi/cpp/completion_callback.h"
-#include "ppapi/cpp/var.h"
-#include "pi_generator.h"
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/image_data.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/utility/completion_callback_factory.h"
namespace {
const int kPthreadMutexSuccess = 0;
@@ -23,16 +27,91 @@ const uint32_t kRedMask = 0xff0000;
const uint32_t kBlueMask = 0xff;
const uint32_t kRedShift = 16;
const uint32_t kBlueShift = 0;
+} // namespace
-// This is called by the browser when the 2D context has been flushed to the
-// browser window.
-void FlushCallback(void* data, int32_t result) {
- static_cast<pi_generator::PiGenerator*>(data)->set_flush_pending(false);
-}
+class PiGeneratorInstance : public pp::Instance {
+ public:
+ explicit PiGeneratorInstance(PP_Instance instance);
+ virtual ~PiGeneratorInstance();
-} // namespace
+ // Start up the ComputePi() thread.
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
+
+ // Update the graphics context to the new size, and regenerate |pixel_buffer_|
+ // to fit the new size as well.
+ virtual void DidChangeView(const pp::View& view);
+
+ // Called by the browser to handle the postMessage() call in Javascript.
+ // The message in this case is expected to contain the string 'paint', and
+ // if so this invokes the Paint() function. If |var_message| is not a string
+ // type, or contains something other than 'paint', this method posts an
+ // invalid value for Pi (-1.0) back to the browser.
+ virtual void HandleMessage(const pp::Var& var_message);
+
+ // Return a pointer to the pixels represented by |pixel_buffer_|. When this
+ // method returns, the underlying |pixel_buffer_| object is locked. This
+ // call must have a matching UnlockPixels() or various threading errors
+ // (e.g. deadlock) will occur.
+ uint32_t* LockPixels();
+ // Release the image lock acquired by LockPixels().
+ void UnlockPixels() const;
+
+ // Flushes its contents of |pixel_buffer_| to the 2D graphics context. The
+ // ComputePi() thread fills in |pixel_buffer_| pixels as it computes Pi.
+ // This method is called by HandleMessage when a message containing 'paint'
+ // is received. Echos the current value of pi as computed by the Monte Carlo
+ // method by posting the value back to the browser.
+ void Paint();
+
+ bool quit() const { return quit_; }
+
+ // |pi_| is computed in the ComputePi() thread.
+ double pi() const { return pi_; }
+
+ int width() const {
+ return pixel_buffer_ ? pixel_buffer_->size().width() : 0;
+ }
+ int height() const {
+ return pixel_buffer_ ? pixel_buffer_->size().height() : 0;
+ }
-namespace pi_generator {
+ // Indicate whether a flush is pending. This can only be called from the
+ // main thread; it is not thread safe.
+ bool flush_pending() const { return flush_pending_; }
+ void set_flush_pending(bool flag) { flush_pending_ = flag; }
+
+ private:
+ // Create and initialize the 2D context used for drawing.
+ void CreateContext(const pp::Size& size, float device_scale);
+ // Destroy the 2D drawing context.
+ void DestroyContext();
+ // Push the pixels to the browser, then attempt to flush the 2D context. If
+ // there is a pending flush on the 2D context, then update the pixels only
+ // and do not flush.
+ void FlushPixelBuffer();
+
+ void FlushCallback(int32_t result);
+
+ bool IsContextValid() const { return graphics_2d_context_ != NULL; }
+
+ pp::CompletionCallbackFactory<PiGeneratorInstance> callback_factory_;
+ mutable pthread_mutex_t pixel_buffer_mutex_;
+ pp::Graphics2D* graphics_2d_context_;
+ pp::ImageData* pixel_buffer_;
+ bool flush_pending_;
+ bool quit_;
+ pthread_t compute_pi_thread_;
+ int thread_create_result_;
+ double pi_;
+ float device_scale_;
+
+ // ComputePi() estimates Pi using Monte Carlo method and it is executed by a
+ // separate thread created in SetWindow(). ComputePi() puts kMaxPointCount
+ // points inside the square whose length of each side is 1.0, and calculates
+ // the ratio of the number of points put inside the inscribed quadrant divided
+ // by the total number of random points to get Pi/4.
+ static void* ComputePi(void* param);
+};
// A small helper RAII class that implements a scoped pthread_mutex lock.
class ScopedMutexLock {
@@ -55,7 +134,7 @@ class ScopedMutexLock {
// A small helper RAII class used to acquire and release the pixel lock.
class ScopedPixelLock {
public:
- explicit ScopedPixelLock(PiGenerator* image_owner)
+ explicit ScopedPixelLock(PiGeneratorInstance* image_owner)
: image_owner_(image_owner), pixels_(image_owner->LockPixels()) {}
~ScopedPixelLock() {
@@ -66,14 +145,13 @@ class ScopedPixelLock {
uint32_t* pixels() const { return pixels_; }
private:
- PiGenerator* image_owner_; // Weak reference.
- uint32_t* pixels_; // Weak reference.
-
- ScopedPixelLock(); // Not implemented, do not use.
+ PiGeneratorInstance* image_owner_; // Weak reference.
+ uint32_t* pixels_; // Weak reference.
};
-PiGenerator::PiGenerator(PP_Instance instance)
+PiGeneratorInstance::PiGeneratorInstance(PP_Instance instance)
: pp::Instance(instance),
+ callback_factory_(this),
graphics_2d_context_(NULL),
pixel_buffer_(NULL),
flush_pending_(false),
@@ -84,7 +162,7 @@ PiGenerator::PiGenerator(PP_Instance instance)
pthread_mutex_init(&pixel_buffer_mutex_, NULL);
}
-PiGenerator::~PiGenerator() {
+PiGeneratorInstance::~PiGeneratorInstance() {
quit_ = true;
if (thread_create_result_ == 0) {
pthread_join(compute_pi_thread_, NULL);
@@ -96,7 +174,7 @@ PiGenerator::~PiGenerator() {
pthread_mutex_destroy(&pixel_buffer_mutex_);
}
-void PiGenerator::DidChangeView(const pp::View& view) {
+void PiGeneratorInstance::DidChangeView(const pp::View& view) {
pp::Size size = view.GetRect().size();
float device_scale = view.GetDeviceScale();
size.set_width(static_cast<int>(size.width() * device_scale));
@@ -121,13 +199,15 @@ void PiGenerator::DidChangeView(const pp::View& view) {
}
}
-bool PiGenerator::Init(uint32_t argc, const char* argn[], const char* argv[]) {
+bool PiGeneratorInstance::Init(uint32_t argc,
+ const char* argn[],
+ const char* argv[]) {
thread_create_result_ =
pthread_create(&compute_pi_thread_, NULL, ComputePi, this);
return thread_create_result_ == 0;
}
-uint32_t* PiGenerator::LockPixels() {
+uint32_t* PiGeneratorInstance::LockPixels() {
void* pixels = NULL;
// Do not use a ScopedMutexLock here, since the lock needs to be held until
// the matching UnlockPixels() call.
@@ -139,7 +219,7 @@ uint32_t* PiGenerator::LockPixels() {
return reinterpret_cast<uint32_t*>(pixels);
}
-void PiGenerator::HandleMessage(const pp::Var& var_message) {
+void PiGeneratorInstance::HandleMessage(const pp::Var& var_message) {
if (!var_message.is_string()) {
PostMessage(pp::Var(kInvalidPiValue));
}
@@ -151,11 +231,11 @@ void PiGenerator::HandleMessage(const pp::Var& var_message) {
}
}
-void PiGenerator::UnlockPixels() const {
+void PiGeneratorInstance::UnlockPixels() const {
pthread_mutex_unlock(&pixel_buffer_mutex_);
}
-void PiGenerator::Paint() {
+void PiGeneratorInstance::Paint() {
ScopedMutexLock scoped_mutex(&pixel_buffer_mutex_);
if (!scoped_mutex.is_valid()) {
return;
@@ -168,7 +248,8 @@ void PiGenerator::Paint() {
PostMessage(pi_estimate);
}
-void PiGenerator::CreateContext(const pp::Size& size, float device_scale) {
+void PiGeneratorInstance::CreateContext(const pp::Size& size,
+ float device_scale) {
ScopedMutexLock scoped_mutex(&pixel_buffer_mutex_);
if (!scoped_mutex.is_valid()) {
return;
@@ -186,7 +267,7 @@ void PiGenerator::CreateContext(const pp::Size& size, float device_scale) {
}
}
-void PiGenerator::DestroyContext() {
+void PiGeneratorInstance::DestroyContext() {
ScopedMutexLock scoped_mutex(&pixel_buffer_mutex_);
if (!scoped_mutex.is_valid()) {
return;
@@ -197,7 +278,7 @@ void PiGenerator::DestroyContext() {
graphics_2d_context_ = NULL;
}
-void PiGenerator::FlushPixelBuffer() {
+void PiGeneratorInstance::FlushPixelBuffer() {
if (!IsContextValid())
return;
// Note that the pixel lock is held while the buffer is copied into the
@@ -206,15 +287,22 @@ void PiGenerator::FlushPixelBuffer() {
if (flush_pending())
return;
set_flush_pending(true);
- graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this));
+ graphics_2d_context_->Flush(
+ callback_factory_.NewCallback(&PiGeneratorInstance::FlushCallback));
}
-void* PiGenerator::ComputePi(void* param) {
+// This is called by the browser when the 2D context has been flushed to the
+// browser window.
+void PiGeneratorInstance::FlushCallback(int32_t result) {
+ set_flush_pending(false);
+}
+
+void* PiGeneratorInstance::ComputePi(void* param) {
int count = 0; // The number of points put inside the inscribed quadrant.
unsigned int seed = 1;
srand(seed);
- PiGenerator* pi_generator = static_cast<PiGenerator*>(param);
+ PiGeneratorInstance* pi_generator = static_cast<PiGeneratorInstance*>(param);
for (int i = 1; i <= kMaxPointCount && !pi_generator->quit(); ++i) {
ScopedPixelLock scoped_pixel_lock(pi_generator);
uint32_t* pixel_bits = scoped_pixel_lock.pixels();
@@ -248,4 +336,16 @@ void* PiGenerator::ComputePi(void* param) {
return 0;
}
-} // namespace pi_generator
+class PiGeneratorModule : public pp::Module {
+ public:
+ PiGeneratorModule() : pp::Module() {}
+ virtual ~PiGeneratorModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new PiGeneratorInstance(instance);
+ }
+};
+
+namespace pp {
+Module* CreateModule() { return new PiGeneratorModule(); }
+} // namespace pp

Powered by Google App Engine
This is Rietveld 408576698