Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 35 additions & 67 deletions Common/Cpp/ListenerSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define PokemonAutomation_ListenerSet_H

#include <exception>
#include <list>
#include <map>
#include <atomic>
//#include "Common/Cpp/PrettyPrint.h"
Expand Down Expand Up @@ -97,23 +98,20 @@ class ListenerSet{
struct Node{
SpinLock lock;
ListenerType& listener;
Node* next = nullptr;
Node** prevs_next = nullptr;

#ifdef PA_DEBUG_ListenerSet
LifetimeSanitizer sanitizer;
#endif

Node(ListenerSet& parent, ListenerType& p_listener)
: listener(p_listener)
, prevs_next(&parent.m_list)
#ifdef PA_DEBUG_ListenerSet
, sanitizer("Node")
#endif
{}
};
Node* m_list = nullptr;
std::map<ListenerType*, Node> m_listeners;
std::list<Node> m_list;
std::map<ListenerType*, typename std::list<Node>::iterator> m_listeners;

#ifdef PA_DEBUG_ListenerSet
LifetimeSanitizer m_sanitizer;
Expand All @@ -140,23 +138,22 @@ void ListenerSet<ListenerType>::add(ListenerType& listener){
auto scope = m_sanitizer.check_scope();
#endif
WriteSpinLock lg(m_lock, m_suppress_lock_prints ? nullptr : "ListenerSet::add()");
auto ret = m_listeners.emplace(
std::piecewise_construct,
std::forward_as_tuple(&listener),
std::forward_as_tuple(*this, listener)
);
if (!ret.second){
return;
}
Node& node = ret.first->second;
#ifdef PA_DEBUG_ListenerSet
node.sanitizer.check_usage();
#endif
if (m_list != nullptr){
m_list->prevs_next = &node.next;

auto iter = m_list.emplace(m_list.end(), *this, listener);
try{
auto ret = m_listeners.emplace(
std::piecewise_construct,
std::forward_as_tuple(&listener),
std::forward_as_tuple(iter)
);
if (!ret.second){
m_list.erase(iter);
return;
}
}catch (...){
m_list.erase(iter);
throw;
}
node.next = m_list;
m_list = &node;
m_count.store(m_listeners.size(), std::memory_order_release);
}
template <typename ListenerType>
Expand All @@ -174,13 +171,13 @@ void ListenerSet<ListenerType>::remove(ListenerType& listener) noexcept{
return;
}

Node& node = iter->second;
typename std::list<Node>::iterator node = iter->second;

#ifdef PA_DEBUG_ListenerSet
node.sanitizer.check_usage();
node->sanitizer.check_usage();
#endif

if (!node.lock.try_acquire_write()){
if (!node->lock.try_acquire_write()){
#if 0
if (!printed){
try{
Expand All @@ -194,18 +191,7 @@ void ListenerSet<ListenerType>::remove(ListenerType& listener) noexcept{

// std::cout << "node = " << &node.sanitizer << " : " << &node.prev->sanitizer << " : " << &node.next->sanitizer << std::endl;

*node.prevs_next = node.next;
if (node.next){
#ifdef PA_DEBUG_ListenerSet
node.next->sanitizer.check_usage();
#endif
node.next->prevs_next = node.prevs_next;
}

#ifdef PA_DEBUG_ListenerSet
node.sanitizer.check_usage();
#endif

m_list.erase(node);
m_listeners.erase(iter);
m_count.store(m_listeners.size(), std::memory_order_release);
return;
Expand All @@ -228,30 +214,19 @@ bool ListenerSet<ListenerType>::try_remove(ListenerType& listener) noexcept{
return true;
}

Node& node = iter->second;
if (!node.lock.try_acquire_write()){
typename std::list<Node>::iterator node = iter->second;
if (!node->lock.try_acquire_write()){
try{
std::cout << "ListenerSet::try_remove(): Fail inner." << std::endl;
}catch (...){}
return false;
}

#ifdef PA_DEBUG_ListenerSet
node.sanitizer.check_usage();
#endif

*node.prevs_next = node.next;
if (node.next){
#ifdef PA_DEBUG_ListenerSet
node.next->sanitizer.check_usage();
#endif
node.next->prevs_next = node.prevs_next;
}

#ifdef PA_DEBUG_ListenerSet
node.sanitizer.check_usage();
node->sanitizer.check_usage();
#endif

m_list.erase(node);
m_listeners.erase(iter);
m_count.store(m_listeners.size(), std::memory_order_release);
m_lock.unlock_write();
Expand All @@ -273,28 +248,23 @@ void ListenerSet<ListenerType>::run_method(Function function, Args&&... args){

m_lock.acquire_read();

Node* node = m_list;
while (node){
for (Node& node : m_list){
{
ReadSpinLock lg(node->lock, m_suppress_lock_prints ? nullptr : "ListenerSet::run_method()");
ReadSpinLock lg(node.lock, m_suppress_lock_prints ? nullptr : "ListenerSet::run_method()");

#ifdef PA_DEBUG_ListenerSet
node->sanitizer.check_usage();
node.sanitizer.check_usage();
#endif
m_lock.unlock_read();
try{
(node->listener.*function)(std::forward<Args>(args)...);
(node.listener.*function)(std::forward<Args>(args)...);
}catch (...){
if (!err){
err = std::current_exception();
}
}
m_lock.acquire_read();
}
#ifdef PA_DEBUG_ListenerSet
node->sanitizer.check_usage();
#endif
node = node->next;
}

m_lock.unlock_read();
Expand All @@ -317,18 +287,17 @@ void ListenerSet<ListenerType>::run_on_all(Lambda&& lambda){

m_lock.acquire_read();

Node* node = m_list;
while (node){
for (Node& node : m_list){
bool return_now = false;
{
ReadSpinLock lg(node->lock, m_suppress_lock_prints ? nullptr : "ListenerSet::run_on_all()");
ReadSpinLock lg(node.lock, m_suppress_lock_prints ? nullptr : "ListenerSet::run_on_all()");

#ifdef PA_DEBUG_ListenerSet
node->sanitizer.check_usage();
node.sanitizer.check_usage();
#endif
m_lock.unlock_read();
try{
return_now = lambda(node->listener);
return_now = lambda(node.listener);
}catch (...){
if (!err){
err = std::current_exception();
Expand All @@ -340,9 +309,8 @@ void ListenerSet<ListenerType>::run_on_all(Lambda&& lambda){
break;
}
#ifdef PA_DEBUG_ListenerSet
node->sanitizer.check_usage();
node.sanitizer.check_usage();
#endif
node = node->next;
}

m_lock.unlock_read();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ void VideoOverlaySession::set(const VideoOverlayOption& option){
void VideoOverlaySession::stats_thread(){
std::unique_lock<Mutex> lg(m_stats_lock);
while (!m_stopping){
std::vector<OverlayStatSnapshot> lines;
m_stats.run_on_all([&](OverlayStat& stat){
OverlayStatSnapshot snapshot = stat.get_current();
if (!snapshot.text.empty()){
lines.emplace_back(std::move(snapshot));
}
return false;
});
{
std::vector<OverlayStatSnapshot> lines;
WriteSpinLock lg0(m_lock, PA_CURRENT_FUNCTION);
for (const auto& stat : m_stats_order){
OverlayStatSnapshot snapshot = stat->get_current();
if (!snapshot.text.empty()){
lines.emplace_back(std::move(snapshot));
}
}
m_stat_lines = std::move(lines);
}
m_stats_cv.wait_for(lg, std::chrono::milliseconds(100));
Expand Down Expand Up @@ -117,31 +118,10 @@ void VideoOverlaySession::set_enabled_log(bool enabled){
//

void VideoOverlaySession::add_stat(OverlayStat& stat){
WriteSpinLock lg(m_lock, PA_CURRENT_FUNCTION);
auto map_iter = m_stats.find(&stat);
if (map_iter != m_stats.end()){
return;
}

m_stats_order.emplace_back(&stat);
auto list_iter = m_stats_order.end();
--list_iter;
try{
m_stats.emplace(&stat, list_iter);
}catch (...){
m_stats_order.pop_back();
throw;
}
m_stats.add(stat);
}
void VideoOverlaySession::remove_stat(OverlayStat& stat){
WriteSpinLock lg(m_lock, PA_CURRENT_FUNCTION);
auto iter = m_stats.find(&stat);
if (iter == m_stats.end()){
return;
}

m_stats_order.erase(iter->second);
m_stats.erase(iter);
m_stats.remove(stat);
}

std::vector<OverlayStatSnapshot> VideoOverlaySession::stats() const{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "Common/Cpp/Concurrency/Mutex.h"
#include "Common/Cpp/Concurrency/ConditionVariable.h"
#include "Common/Cpp/Concurrency/AsyncTask.h"
#include "Common/Cpp/Concurrency/Thread.h"
#include "VideoOverlay.h"
#include "VideoOverlayOption.h"

Expand Down Expand Up @@ -146,8 +145,7 @@ class VideoOverlaySession : public VideoOverlay{
std::set<const OverlayImage*> m_images;
std::deque<OverlayLogLine> m_log_texts;

std::list<OverlayStat*> m_stats_order;
std::map<OverlayStat*, std::list<OverlayStat*>::iterator> m_stats;
ListenerSet<OverlayStat> m_stats;

ListenerSet<ContentListener> m_listeners;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ void BattleDialogDetector::make_overlays(VideoOverlaySet& items) const{
bool BattleDialogDetector::detect(const ImageViewRGB32& screen){
ImageStats bottom = image_stats(extract_box_reference(screen, m_bottom));
// cout << "bottom: " << bottom.average << bottom.stddev << endl;
if (!is_grey(bottom, 0, 200, 10)){
if (!is_grey(bottom, 0, 200, 5)){
return false;
}
ImageStats left = image_stats(extract_box_reference(screen, m_left));
// cout << "left: " << left.average << left.stddev << endl;
if (!is_grey(left, 0, 200, 5)){
if (!is_grey(left, 0, 200, 3)){
return false;
}
ImageStats right = image_stats(extract_box_reference(screen, m_right));
// cout << "right: " << right.average << right.stddev << endl;
if (!is_grey(right, 0, 200, 5)){
if (!is_grey(right, 0, 200, 3)){
return false;
}

Expand Down
Loading