-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor and modernize the native interface #35
refactor and modernize the native interface #35
Conversation
Make it work on macOS
FIX: race condition due to condition variable misuse
Open build and threading issues:
|
Ahhh. This would be greatto get rid of opa! Will look into your issues with macos. I need to start acquiring more time at work for this project. :) |
binding.gyp
Outdated
"xcode_settings": { | ||
"OTHER_CFLAGS": [ | ||
"-std=c++0x", | ||
"-stdlib=libc++" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can update this to:
"-std=c++11"
Shouldn't need to define stdlib=c++
FIX: build with node.js v4 on macOS
We are seeing several races and dead locks both on Travis and AppVeyor. Frankly we believe that they've been in the code base before (see build results of latest master merge). It might be that implementing |
…TL' into refactor/remove_opa_and_use_cpp11_STL
Refactor/remove opa and use cpp11 stl
Refactor: use std::thread rather then pthread_t
…1_STL use semaphore to wait until thread is running
The polling system actually needs to be removed all together with a throttled callback mechanism. I'm thinking of using something similar in pattern to what I'm doing in https://github.com/implausible/find-git-repositories/blob/master/src/FindGitRepos.cpp#L134. Honestly, the the synchronization behavior of the polling thread is not my proudest set up. |
Agreed. That sounds a lot better than another spinning thread polling the |
From our side, this PR is complete and we'd be happy for feedback. Frankly this became a much bigger patch than we initially thought. There are a few more things to be done from our perspective, but I suggest to open another issue for that. Summary of changes:
|
I haven't had a chance to sit down and review this seriously; however, the only immediate concern I have is the use of |
Thanks for your quick reply! Regarding your concerns:
No. In fact the
Did you measure any lock contention on a mutex-based approach before? While I agree that lock free data structures are fancy, I wouldn't go down that road without evident benefits.
I guess you are afraid to starve the javascript execution because of a quickly spinning file event watcher. This seems reasonable but I would argue that it is very unlikely. The Both Windows and Linux use blocking and/or asynchronous calls ( Anyhow, I agree that it would be interesting to benchmark this. |
Following up on that with some quick'n'dirty measuring attempt using I ran a minimal C++ program that would frequently retrieve all file events from the for i in $(seq 1 1000); do
mkdir -p $i
for j in $(seq 1 1000); do
echo "foobar" > $i/$j
done
done The graph below shows how often That means for a reasonable query frequency of say 100ms, the polling thread would only experience around one blocking Edit: The same test on windows and linux show comparable results. |
That should be sufficient. Thank you for providing some numbers. |
@@ -15,7 +15,7 @@ install: | |||
# Get the latest stable version of Node.js or io.js | |||
- ps: Install-Product node $env:nodejs_version | |||
# install modules | |||
- npm install --msvs_version=2013 | |||
- npm install --msvs_version=2015 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this still build with msvs_version set to 2013?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let us use the 2013 compiler :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a first pass. I just stopped at the windows controller/watcher refactor. Will pick up again tomorrow. Most of what I've noticed today is just trying to keep the voice of the project consistent. It's looking great. Will have more on the refactor soon.
includes/SingleshotSemaphore.h
Outdated
* Blocks the calling thread until the semaphore is signaled asynchronously. | ||
* If `signal()` has been called on the semaphore already, this won't block. | ||
*/ | ||
void wait() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of the project is using 2 spaces for indent and opening braces on the function definition (generally). We should perhaps invest some time in declaring a public style guide now that we are receiving additional contributions, but in general we should try to adhere to the style already used in the base.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should use the llvm styleguide
https://llvm.org/docs/CodingStandards.html
includes/NativeInterface.h
Outdated
|
||
std::string getError(); | ||
std::vector<Event *> *getEvents(); | ||
std::vector<Event *>* getEvents(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're going to need to pick a style, especially in this PR you're swapping between voices. Pointer/reference operator should live on the variable name since comma that is what the operator affects. IE:
int* a, b;
in the above, only a is an integer pointer, where as it seems to be implied that both a and b are integer pointers. I will add a style comment anywhere that I've noticed that.
includes/Queue.h
Outdated
std::string directory, | ||
std::string fileA, | ||
std::string fileB = "" | ||
const std::string& directory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style please :)
includes/SingleshotSemaphore.h
Outdated
} | ||
|
||
private: | ||
std::mutex mMutex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aren't enforcing this variable alignment in the code base. Single space will suffice. Thanks!
if (mNSFW->mInterface == NULL) { | ||
uv_mutex_unlock(&mNSFW->mInterfaceLock); | ||
return; | ||
} | ||
uv_mutex_unlock(&mNSFW->mInterfaceLock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the lock manage here is really difficult. I think we can do better, but for another PR. Just to talk about what I'm currently mulling over...
We should consider building a mapping interface between the native watcher and the javascript head. When an NSFW is created on the js side, it should assign itself the next id and create a native file watcher. The native file watcher should know the id or have a callback which knows of the id and be able to reference the js side through that id (when performing callbacks). When the nsfw module itself halts, we should let the native side clean up on its own time, but sever the map between the native and js layer... That way we don't need to sync at all in the stop worker!
What do you think? Just thoughts for another PR I think.
src/Queue.cpp
Outdated
|
||
Event *event = node->event; | ||
delete node; | ||
auto& front = queue.front(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style please.
src/NativeInterface.cpp
Outdated
} | ||
|
||
return events; | ||
std::vector<Event *>* NativeInterface::getEvents() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style please.
src/Queue.cpp
Outdated
const auto queueSize = queue.size(); | ||
std::unique_ptr<std::vector<Event*>> events(new std::vector<Event*>(queueSize, nullptr)); | ||
for (size_t i = 0; i < queueSize; ++i) { | ||
auto& front = queue.front(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style please.
src/Queue.cpp
Outdated
|
||
OPA_Queue_enqueue(&mQueue, node, EventNode, header); | ||
OPA_incr_int(&mNumEvents); | ||
void EventQueue::enqueue(const EventType type, const std::string& directory, const std::string& fileA, const std::string& fileB) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style :D..
scheduleRunLoopWork, | ||
(void *)this | ||
); | ||
mRunLoopThread = std::thread([] (RunLoop *rl) { rl->work(); }, this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh, lambdas.
…b.com/xqp/nsfw into refactor/remove_opa_and_use_cpp11_STL
About style issues: |
we should use the new msvc 15 because the older version can not compile the actual code version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly style and some areas we could improve clarity, but this is looking very solid. Thanks!
src/win32/Controller.cpp
Outdated
@@ -0,0 +1,73 @@ | |||
#include "../includes/win32/Controller.h" | |||
|
|||
static std::wstring convertMultiByteToWideChar(const std::string &multiByte) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code base is currently using curly brace on the opening line.
src/win32/Controller.cpp
Outdated
} | ||
|
||
HANDLE Controller::openDirectory(const std::wstring &path) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
src/win32/Controller.cpp
Outdated
} | ||
|
||
Controller::~Controller() | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open on same line, please
src/win32/Controller.cpp
Outdated
} | ||
|
||
std::string Controller::getError() | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same line here
src/win32/Controller.cpp
Outdated
return mWatcher->getError(); | ||
} | ||
|
||
bool Controller::hasErrored() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
src/win32/Watcher.cpp
Outdated
void Watcher::stop() | ||
{ | ||
mRunning = false; | ||
QueueUserAPC([](__in ULONG_PTR) {}, mRunner.native_handle(), (ULONG_PTR)this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a comment here, it would be a lot faster for future contributors to recognize that this is to wake up the SleepEx above so that the watcher's loop exits cleanly.
src/win32/Watcher.cpp
Outdated
} | ||
} | ||
|
||
void Watcher::stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ on the same line please
return; | ||
} | ||
|
||
QueueUserAPC([](__in ULONG_PTR self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
life is so much better with lambdas.
src/win32/Watcher.cpp
Outdated
mRunner.join(); | ||
} | ||
|
||
void Watcher::setError(const std::string &error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ on the same line please
src/win32/Watcher.cpp
Outdated
} | ||
|
||
|
||
std::string Watcher::getError() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ on the same line please
FIX: review comments
FIX: missing header adaption
We had a test failure on linux in the test for listening for the creation of a deeply nested filex; however, I have seen that failure in master. I don't think it's related to anything you've done, since the refactor there is minimal and should have no change in semantics. I've gone ahead and restarted that, test. Though we should open an issue related to discovering why that test fails. |
as discussed yesterday with @maxkorp in #34 here are a bunch of changes.
std::unique_lock<mutex_type>
to be done in future work:
- implement a c++ callback interface to the native filewatchers(in other PR)