@ChristopherWu
2017-03-06T22:54:22.000000Z
字数 9355
阅读 1256
Wine
Implement functions from Concurrency namespace
Abstract: Most of the functions from Concurrency namespace are not implemented. This project plan to implement all of them, which would fix some bugs and benefit wine's behavior on many softwares.
Hi, all
I'm YongHao Hu, a college student majored in Computer Science from Guangdong Pharmaceutical University, China, GMT+08:00. I participated in GSoC of Wine last year and most of the work are finished. I have enough understanding regarding to the Wine community and msvcp/msvcr module.
This year I want to implement functions from Concurrency namespace1.
As Wine had already implemented class Concurrency::critical_section2, SpinWait and Concurrency::details::_GetConcurrency, and I had found information in Microsoft open-source project for cloud-based client-server communication in native code using a modern asynchronous C++ API design3 are helpful for the implementation, I think that I am able to handle this project. By now, I had made some patches as my proof of concept.4
There are many bugs[4-8] relied on functions from Concurrency namespace, this project would fix some bugs and benefit wine's behavior on many softwares.
There are three parts in my plan:
Add tests to critical session.
Implement Class condition variable.
Add tests to condition variable.
Implement Class reader_writer_lock and tests.
Implement Class event and tests.
Implement Class TaskCollection and tests.
Befor April 22
Improve my patch of critical session and learn more about Concurrency.
Learn more about functions from Concurrency namespace.
April 22 – May 23 (Before the official coding time):
Discuss my proposal with my mentor in detail so that I can more clear about my fucture goals.
Try to get my test of critical session accepted by upstream.
Write demo implementation and tests of Class condition variable.
May 23 (Official coding period starts)
Get them upsteam.
June 27th MID TERM EVALUATION
July 16 – Auguest 8(23days):
Implement Class TaskCollection and tests.
Get them upsteam.
August 23th FINAL EVALUATION
A Buffer of two weeks has been kept for any unpredictable delay.
By making this appropriate proposal, I think the project's work can satisfy GSoC's requirement.
As we can refer to some implementation of Microsoft1, do you think it would become easier?
For example, the event class2 can refer to the pplxlinux.h3,
TaskCollection4 can refer to pplx.h5 and
reader_writer_lock6 can refer to pplxlinux.h7 etc.
Do you think such a plan would satisfy GSoC's requirement?
Though Apache License(v2) is not compatible with the (L)GPL2, we can read the code instead of copying them, right?
Thank you very much. :)
I want to mention that even the structures, class and functions have implementation in the open-source project.[1,2,3]
For example, in 1, as far as I am concerned, we can implement Class event in Wine base on this. Of course, we also need to be binary compatible.
class event_impl {
private:
cpprest_synchronization::mutex _lock;
cpprest_synchronization::condition_variable _condition;
bool _signaled;
public:
static const unsigned int timeout_infinite = 0xFFFFFFFF;
event_impl() : _signaled(false) { }
void set() {
cpprest_synchronization::lock_guard lock(_lock);
_signaled = true;
_condition.notify_all();
}
void reset() {
cpprest_synchronization::lock_guard lock(_lock);
_signaled = false;
}
unsigned int wait(unsigned int timeout) {
cpprest_synchronization::unique_lock lock(_lock);
if (timeout == event_impl::timeout_infinite) {
_condition.wait(lock, this -> bool { return _signaled; });
return 0;
} else {
cpprest_synchronization::chrono::milliseconds period(timeout);
auto status = _condition.wait_for(lock, period, this -> bool { return _signaled; });
_ASSERTE(status == _signaled);
// Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite
// Note: this must be consistent with the behavior of the Windows version, which is based on WaitForSingleObjectEx
return status ? 0: event_impl::timeout_infinite;
}
};
agent::agent -> Scheduler -> CurrentScheduler -> SchedulerPolicy
concurrent_queue
#include <ppl.h>
#include <array>
#include <sstream>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
// Print each value from 1 to 5 in parallel.
parallel_for(1, 6, [](int value) {
wstringstream ss;
ss << value << L' ';
wcout << ss.str();
});
}
msvcp120.dll.protected: __thiscall Concurrency::details::_Concurrent_queue_base_v4::_Concurrent_queue_base_v4(unsigned int)
msvcr120.dll.public: __thiscall Concurrency::event::event(void)
#include <ppl.h>
#include <array>
#include <sstream>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
// Print each value from 1 to 5 in parallel.
parallel_for(1, 6, [](int value) {
wstringstream ss;
ss << value << L' ';
wcout << ss.str();
});
}
mmsvcr120.dll.void __cdecl Concurrency::_Trace_ppl_function(struct _GUID const &,unsigned char,enum Concurrency::ConcRT_EventType)
msvcr120.dll.public: __cdecl Concurrency::SchedulerPolicy::SchedulerPolicy(unsigned int,...)
msvcr120.dll.public: __thiscall Concurrency::details::_TaskCollection::_TaskCollection(void)
@ stub -arch=arm public: __cdecl Concurrency::event::event(void)
@ stub -arch=i386 public: __thiscall Concurrency::event::event(void)
@ stub -arch=win64 public: __cdecl Concurrency::event::event(void) __ptr64
@ stub -arch=arm public: __cdecl Concurrency::event::~event(void)
@ stub -arch=i386 public: __thiscall Concurrency::event::~event(void)
@ stub -arch=win64 public: __cdecl Concurrency::event::~event(void) __ptr64
@ stub -arch=arm public: void __cdecl Concurrency::event::reset(void)
@ stub -arch=i386 public: void __thiscall Concurrency::event::reset(void)
@ stub -arch=win64 public: void __cdecl Concurrency::event::reset(void) __ptr64
@ stub -arch=arm public: void __cdecl Concurrency::event::set(void)
@ stub -arch=i386 public: void __thiscall Concurrency::event::set(void)
@ stub -arch=win64 public: void __cdecl Concurrency::event::set(void) __ptr64
@ stub -arch=arm public: unsigned int __cdecl Concurrency::event::wait(unsigned int)
@ stub -arch=i386 public: unsigned int __thiscall Concurrency::event::wait(unsigned int)
@ stub -arch=win64 public: unsigned __int64 __cdecl Concurrency::event::wait(unsigned int) __ptr64
@ stub -arch=win32 public: static unsigned int __cdecl Concurrency::event::wait_for_multiple(class Concurrency::event * *,unsigned int,BOOL,unsigned int)
@ stub -arch=win64 public: static unsigned __int64 __cdecl Concurrency::event::wait_for_multiple(class Concurrency::event * __ptr64 * __ptr64,unsigned __int64,BOOL,unsigned int)
public: __thiscall Concurrency::agent::agent(class Concurrency::Scheduler &)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: __thiscall Concurrency::agent::agent(class Concurrency::ScheduleGroup &)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: __cdecl Concurrency::agent::agent(class Concurrency::ScheduleGroup & __ptr64) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: __thiscall Concurrency::agent::agent(class Concurrency::Scheduler &)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: __cdecl Concurrency::agent::agent(class Concurrency::Scheduler & __ptr64) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: __thiscall Concurrency::agent::agent(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: __cdecl Concurrency::agent::agent(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: virtual __thiscall Concurrency::agent::~agent(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: virtual __cdecl Concurrency::agent::~agent(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: BOOL __thiscall Concurrency::agent::cancel(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: BOOL __cdecl Concurrency::agent::cancel(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 protected: BOOL __thiscall Concurrency::agent::done(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 protected: BOOL __cdecl Concurrency::agent::done(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: BOOL __thiscall Concurrency::agent::start(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: BOOL __cdecl Concurrency::agent::start(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: enum Concurrency::agent_status __thiscall Concurrency::agent::status(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: enum Concurrency::agent_status __cdecl Concurrency::agent::status(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: class Concurrency::ISource<enum Concurrency::agent_status> * __thiscall Concurrency::agent::status_port(void)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: class Concurrency::ISource<enum Concurrency::agent_status> * __ptr64 __cdecl Concurrency::agent::status_port(void) __ptr64
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: static enum Concurrency::agent_status __cdecl Concurrency::agent::wait(class Concurrency::agent *,unsigned int)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: static enum Concurrency::agent_status __cdecl Concurrency::agent::wait(class Concurrency::agent * __ptr64,unsigned int)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: static void __cdecl Concurrency::agent::wait_for_all(unsigned int,class Concurrency::agent * *,enum Concurrency::agent_status *,unsigned int)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: static void __cdecl Concurrency::agent::wait_for_all(unsigned __int64,class Concurrency::agent * __ptr64 * __ptr64,enum Concurrency::agent_status * __ptr64,unsigned int)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win32 public: static void __cdecl Concurrency::agent::wait_for_one(unsigned int,class Concurrency::agent * *,enum Concurrency::agent_status &,unsigned int &,unsigned int)
dlls/msvcp100/msvcp100.spec:@ stub -arch=win64 public: static void __cdecl Concurrency::agent::wait_for_one(unsigned __int64,class Concurrency::agent * __ptr64 * __ptr64,enum Concurrency::agent_status & __ptr64,unsigned __int64 & __ptr64,unsigned int)