]> git.sesse.net Git - casparcg/commitdiff
Merged INFO THREADS from 2.0
authorHelge Norberg <helge.norberg@svt.se>
Wed, 12 Aug 2015 14:04:10 +0000 (16:04 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 12 Aug 2015 14:04:10 +0000 (16:04 +0200)
17 files changed:
common/CMakeLists.txt
common/os/linux/signal_handlers.cpp
common/os/linux/threading.cpp [moved from common/os/linux/scheduling.cpp with 90% similarity]
common/os/threading.h [moved from common/os/scheduling.h with 94% similarity]
common/os/windows/threading.cpp [moved from common/os/windows/scheduling.cpp with 91% similarity]
common/os/windows/win32_exception.cpp
common/thread_info.cpp [new file with mode: 0644]
common/thread_info.h [new file with mode: 0644]
core/consumer/output.cpp
core/diagnostics/osd_graph.cpp
core/mixer/mixer.cpp
core/mixer/mixer.h
core/producer/stage.cpp
core/producer/stage.h
core/thumbnail_generator.cpp
core/video_channel.cpp
protocol/amcp/AMCPCommandsImpl.cpp

index 73c97002a62f3a025899a46df56637c3276c9f8a..27938f4ba14a7da3fd0d611935957aa8d39d69ed 100644 (file)
@@ -11,6 +11,7 @@ set(SOURCES
                log.cpp
                polling_filesystem_monitor.cpp
                stdafx.cpp
+               thread_info.cpp
                tweener.cpp
                utf.cpp
 )
@@ -24,7 +25,7 @@ if (MSVC)
                        os/windows/filesystem.cpp
                        os/windows/page_locked_allocator.cpp
                        os/windows/prec_timer.cpp
-                       os/windows/scheduling.cpp
+                       os/windows/threading.cpp
                        os/windows/stack_trace.cpp
                        os/windows/system_info.cpp
                        os/windows/win32_exception.cpp
@@ -36,7 +37,7 @@ elseif (CMAKE_COMPILER_IS_GNUCXX)
                        os/linux/filesystem.cpp
                        os/linux/prec_timer.cpp
                        os/linux/signal_handlers.cpp
-                       os/linux/scheduling.cpp
+                       os/linux/threading.cpp
                        os/linux/stack_trace.cpp
                        os/linux/system_info.cpp
        )
@@ -49,7 +50,7 @@ set(HEADERS
                os/filesystem.h
                os/general_protection_fault.h
                os/page_locked_allocator.h
-               os/scheduling.h
+               os/threading.h
                os/stack_trace.h
                os/system_info.h
 
@@ -80,6 +81,7 @@ set(HEADERS
                scope_exit.h
                semaphore.h
                stdafx.h
+               thread_info.h
                timer.h
                tweener.h
                utf.h
index 457c674b8f5d9ad5dcaccb2c05e6d10166f39092..e87cc69e7c4d535582c90f3178927c4bdeb3b914 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "../../except.h"
 #include "../../log.h"
+#include "../../thread_info.h"
 
 #include <signal.h>
 
@@ -51,6 +52,9 @@ void ensure_gpf_handler_installed_for_thread(
                const char* thread_description)
 {
        static auto install = []() { do_install_handlers(); return 0; } ();
+       
+       if (thread_description)
+               get_thread_info().name = thread_description;
 }
 
 }
similarity index 90%
rename from common/os/linux/scheduling.cpp
rename to common/os/linux/threading.cpp
index b0fed5b88db9dd6240bfbfd7cecec3fdb87a5b41..bab082b73ff678f639a58b59fcc3db8b0188c758 100644 (file)
 
 #include "../../stdafx.h"
 
-#include "../scheduling.h"
+#include "../threading.h"
 
 namespace caspar {
-       
+
 void set_priority_of_current_thread(thread_priority priority)
 {
        // TODO: implement
 }
 
+std::int64_t get_current_thread_id()
+{
+       // TODO: implement
+       return 0;
+}
+
 }
similarity index 94%
rename from common/os/scheduling.h
rename to common/os/threading.h
index c5f61e893bbb0e0a25a430251bc6ae4be9e7eff4..1ad3420952da337e1216348350816d30d621fbd9 100644 (file)
@@ -21,6 +21,8 @@
 
 #pragma once
 
+#include <cstdint>
+
 namespace caspar {
 
 enum class thread_priority
@@ -29,5 +31,6 @@ enum class thread_priority
 };
 
 void set_priority_of_current_thread(thread_priority priority);
+std::int64_t get_current_thread_id();
 
 }
similarity index 91%
rename from common/os/windows/scheduling.cpp
rename to common/os/windows/threading.cpp
index 9a76fc18e893582e2a80986b8ecf2a188080823d..c84c4b7f3c506ed7c87af8f1e33157c792efbb8a 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "../../stdafx.h"
 
-#include "../scheduling.h"
+#include "../threading.h"
 
 #include "windows.h"
 
@@ -33,4 +33,9 @@ void set_priority_of_current_thread(thread_priority priority)
                SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);
 }
 
+std::int64_t get_current_thread_id()
+{
+       return GetCurrentThreadId();
+}
+
 }
index 1c5c899549b7e116696d685491355b98a07415ee..cd3428b884aa7d32415b4d7586af3e942fc3795d 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <boost/thread.hpp>
 
+#include "../../thread_info.h"
 #include "windows.h"
 
 namespace caspar { namespace detail {
@@ -65,7 +66,10 @@ void ensure_gpf_handler_installed_for_thread(
                install_gpf_handler();
 
                if (thread_description)
+               {
                        detail::SetThreadName(GetCurrentThreadId(), thread_description);
+                       get_thread_info().name = thread_description;
+               }
        }
 }
 
diff --git a/common/thread_info.cpp b/common/thread_info.cpp
new file mode 100644 (file)
index 0000000..3937762
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "stdafx.h"
+
+#include "thread_info.h"
+#include "os/threading.h"
+
+#include <map>
+
+#include <boost/thread/tss.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace caspar {
+
+class enumerable_thread_infos
+{
+       boost::mutex                                                                                            mutex_;
+       std::map<void*, std::weak_ptr<thread_info>>                                     enumerable_;
+       boost::thread_specific_ptr<std::shared_ptr<thread_info>>        infos_;
+public:
+       static enumerable_thread_infos& get_instance()
+       {
+               static enumerable_thread_infos instance;
+
+               return instance;
+       }
+
+       std::vector<spl::shared_ptr<thread_info>> get_thread_infos()
+       {
+               boost::lock_guard<boost::mutex> lock(mutex_);
+
+               std::vector<spl::shared_ptr<thread_info>> result;
+               result.reserve(enumerable_.size());
+
+               for (auto it = enumerable_.begin(); it != enumerable_.end();)
+               {
+                       auto lock = it->second.lock();
+
+                       if (lock)
+                       {
+                               result.push_back(spl::make_shared_ptr(lock));
+                               ++it;
+                       }
+                       else
+                       {
+                               it = enumerable_.erase(it);
+                       }
+               }
+
+               std::sort(result.begin(), result.end(), [](const spl::shared_ptr<thread_info>& lhs, const spl::shared_ptr<thread_info>& rhs) { return lhs->native_id < rhs->native_id; });
+
+               return result;
+       }
+
+       thread_info& get_thread_info()
+       {
+               auto local = infos_.get();
+
+               if (!local)
+               {
+                       std::unique_ptr<thread_info> p(new thread_info);
+                       local = new std::shared_ptr<thread_info>(p.get(), [this](thread_info* p)
+                       {
+                               boost::lock_guard<boost::mutex> lock(mutex_);
+                               enumerable_.erase(p);
+                               delete p;
+                       });
+                       p.release();
+                       infos_.reset(local);
+                       boost::lock_guard<boost::mutex> lock(mutex_);
+                       enumerable_.insert(std::make_pair(local->get(), *local));
+               }
+
+               return **local;
+       }
+};
+
+thread_info::thread_info()
+       : native_id(get_current_thread_id())
+{
+}
+
+thread_info& get_thread_info()
+{
+       return enumerable_thread_infos::get_instance().get_thread_info();
+}
+
+std::vector<spl::shared_ptr<thread_info>> get_thread_infos()
+{
+       return enumerable_thread_infos::get_instance().get_thread_infos();
+}
+
+}
diff --git a/common/thread_info.h b/common/thread_info.h
new file mode 100644 (file)
index 0000000..0518786
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include <string>
+#include <cstdint>
+#include <vector>
+
+#include "memory.h"
+
+#include <tbb/atomic.h>
+
+#include <boost/thread/thread.hpp>
+
+namespace caspar {
+
+struct thread_info
+{
+       std::string             name;
+       std::int64_t    native_id;
+
+       thread_info();
+};
+
+thread_info& get_thread_info();
+std::vector<spl::shared_ptr<thread_info>> get_thread_infos();
+
+}
index d939cca3a4ac8bfc740148919359adcd053e6efc..debbffbc2544824ca2610683d8c5d204eeaca465 100644 (file)
@@ -60,7 +60,7 @@ struct output::impl
        std::map<int, port>                                     ports_; 
        prec_timer                                                      sync_timer_;
        boost::circular_buffer<const_frame>     frames_;
-       executor                                                        executor_                       = { L"output" };
+       executor                                                        executor_                       = { L"output " + boost::lexical_cast<std::wstring>(channel_index_) };
 public:
        impl(spl::shared_ptr<diagnostics::graph> graph, const video_format_desc& format_desc, int channel_index) 
                : graph_(std::move(graph))
index bd036ea2aa5747c4a72cf0fb3be80779114a0d99..8d3d35f2fb59f849da611fc921f852fa5edbb17c 100644 (file)
@@ -31,7 +31,7 @@
 #include <common/lock.h>
 #include <common/env.h>
 #include <common/prec_timer.h>
-#include <common/os/scheduling.h>
+#include <common/os/threading.h>
 #include <common/timer.h>
 
 #include <SFML/Graphics.hpp>
index 014ae8225f1005c4499e96b36d40758f4cbfc7c8..51e1687a4cfb9b3e0e958d2206d44f7671165172 100644 (file)
@@ -42,6 +42,7 @@
 #include <core/video_format.h>
 
 #include <boost/property_tree/ptree.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <tbb/concurrent_queue.h>
 #include <tbb/spin_mutex.h>
 namespace caspar { namespace core {
 
 struct mixer::impl : boost::noncopyable
-{                              
+{
+       int                                                                     channel_index_;
        spl::shared_ptr<diagnostics::graph> graph_;
        audio_mixer                                                     audio_mixer_;
        spl::shared_ptr<image_mixer>            image_mixer_;
                        
-       executor executor_                                                                      { L"mixer" };
+       executor                                                        executor_               { L"mixer " + boost::lexical_cast<std::wstring>(channel_index_) };
 
 public:
-       impl(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) 
-               : graph_(std::move(graph))
+       impl(int channel_index, spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) 
+               : channel_index_(channel_index)
+               , graph_(std::move(graph))
                , image_mixer_(std::move(image_mixer))
        {                       
                graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8f));
@@ -127,8 +130,8 @@ public:
        }
 };
        
-mixer::mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) 
-       : impl_(new impl(std::move(graph), std::move(image_mixer))){}
+mixer::mixer(int channel_index, spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer) 
+       : impl_(new impl(channel_index, std::move(graph), std::move(image_mixer))){}
 void mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }
 float mixer::get_master_volume() { return impl_->get_master_volume(); }
 std::future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}
index cf4e7545aca01f823649c38b7ba7b51e02a26fae..f1bc4a297fe25972b97dd147014817bf26815316 100644 (file)
@@ -48,7 +48,7 @@ public:
                                        
        // Constructors
        
-       explicit mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer);
+       explicit mixer(int channel_index, spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer);
 
        // Methods
                
index 98630b53b20f74765477e0314ff903ba32ab0908..cb7642b8fb3c16991bfa7780b852dac652b91fce 100644 (file)
 namespace caspar { namespace core {
        
 struct stage::impl : public std::enable_shared_from_this<impl>
-{                              
+{
+       int                                                                                                                                             channel_index_;
        spl::shared_ptr<diagnostics::graph>                                                                             graph_;
-       spl::shared_ptr<monitor::subject>                                                                               monitor_subject_;
-       //reactive::basic_subject<std::map<int, draw_frame>>                                    frames_subject_;
-       std::map<int, layer>                                                                                                    layers_;        
+       spl::shared_ptr<monitor::subject>                                                                               monitor_subject_        = spl::make_shared<monitor::subject>("/stage");
+       std::map<int, layer>                                                                                                    layers_;
        std::map<int, tweened_transform>                                                                                tweens_;
        interaction_aggregator                                                                                                  aggregator_;
        // map of layer -> map of tokens (src ref) -> layer_consumer
        std::map<int, std::map<void*, spl::shared_ptr<write_frame_consumer>>>   layer_consumers_;
-       executor                                                                                                                                executor_;
+       executor                                                                                                                                executor_                       { L"stage " + boost::lexical_cast<std::wstring>(channel_index_) };
 public:
-       impl(spl::shared_ptr<diagnostics::graph> graph) 
-               : graph_(std::move(graph))
-               , monitor_subject_(spl::make_shared<monitor::subject>("/stage"))
+       impl(int channel_index, spl::shared_ptr<diagnostics::graph> graph)
+               : channel_index_(channel_index)
+               , graph_(std::move(graph))
                , aggregator_([=] (double x, double y) { return collission_detect(x, y); })
-               , executor_(L"stage")
        {
                graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));
        }
@@ -441,7 +440,7 @@ public:
        }
 };
 
-stage::stage(spl::shared_ptr<diagnostics::graph> graph) : impl_(new impl(std::move(graph))){}
+stage::stage(int channel_index, spl::shared_ptr<diagnostics::graph> graph) : impl_(new impl(channel_index, std::move(graph))){}
 std::future<std::wstring> stage::call(int index, const std::vector<std::wstring>& params){return impl_->call(index, params);}
 std::future<void> stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms){ return impl_->apply_transforms(transforms); }
 std::future<void> stage::apply_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const tweener& tween){ return impl_->apply_transform(index, transform, mix_duration, tween); }
index 7ef500d194be5de926ed4f6c6b2929c04f0316d5..eb0f37c9d8007d1c46ff34185b17de010405066a 100644 (file)
@@ -57,7 +57,7 @@ public:
 
        // Constructors
 
-       explicit stage(spl::shared_ptr<diagnostics::graph> graph);
+       explicit stage(int channel_index, spl::shared_ptr<diagnostics::graph> graph);
        
        // Methods
 
index 3992778f70abcb11948d50fb3c4a94d314b47ebe..085fee81964b93d050a99c60499d3180d4895297 100644 (file)
@@ -133,7 +133,7 @@ public:
                , image_mixer_(std::move(image_mixer))
                , format_desc_(render_video_mode)
                , output_(spl::make_unique<thumbnail_output>(generate_delay_millis))
-               , mixer_(graph_, image_mixer_)
+               , mixer_(0, graph_, image_mixer_)
                , thumbnail_creator_(thumbnail_creator)
                , media_info_repo_(std::move(media_info_repo))
                , producer_registry_(std::move(producer_registry))
index fcd79535bafad631dc032a8cd5c14266d6762ba3..9eb8998bb37b6a0e114b9b10109cf7f668d98f59 100644 (file)
@@ -71,7 +71,7 @@ struct video_channel::impl final
        caspar::core::mixer                                                                     mixer_;
        caspar::core::stage                                                                     stage_; 
 
-       executor                                                                                        executor_                       { L"video_channel" };
+       executor                                                                                        executor_                       { L"video_channel " + boost::lexical_cast<std::wstring>(index_) };
 public:
        impl(int index, const core::video_format_desc& format_desc, std::unique_ptr<image_mixer> image_mixer)  
                : monitor_subject_(spl::make_shared<monitor::subject>(
@@ -80,8 +80,8 @@ public:
                , format_desc_(format_desc)
                , output_(graph_, format_desc, index)
                , image_mixer_(std::move(image_mixer))
-               , mixer_(graph_, image_mixer_)
-               , stage_(graph_)
+               , mixer_(index, graph_, image_mixer_)
+               , stage_(index, graph_)
        {
                graph_->set_color("tick-time", caspar::diagnostics::color(0.0f, 0.6f, 0.9f));
                graph_->set_text(print());
index bc82652899272527ba03b32759d73244e909d331..ec2151f1ea289584a6232a592b7cbfcb74ba4f6a 100644 (file)
@@ -37,6 +37,7 @@
 #include <common/os/system_info.h>
 #include <common/os/filesystem.h>
 #include <common/base64.h>
+#include <common/thread_info.h>
 
 #include <core/producer/cg_proxy.h>
 #include <core/producer/frame_producer.h>
@@ -2401,6 +2402,27 @@ std::wstring info_queues_command(command_context& ctx)
        return create_info_xml_reply(AMCPCommandQueue::info_all_queues(), L"QUEUES");
 }
 
+void info_threads_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+       sink.short_description(L"Lists all known threads in the server.");
+       sink.syntax(L"INFO THREADS");
+       sink.para()->text(L"Lists all known threads in the server.");
+}
+
+std::wstring info_threads_command(command_context& ctx)
+{
+       std::wstringstream replyString;
+       replyString << L"200 INFO THREADS OK\r\n";
+
+       for (auto& thread : get_thread_infos())
+       {
+               replyString << thread->native_id << L"\t" << u16(thread->name) << L"\r\n";
+       }
+
+       replyString << L"\r\n";
+       return replyString.str();
+}
+
 void diag_describer(core::help_sink& sink, const core::help_repository& repo)
 {
        sink.short_description(L"Open the diagnostics window.");
@@ -2765,6 +2787,7 @@ void register_commands(amcp_command_repository& repo)
        repo.register_command(                  L"Query Commands",              L"INFO SYSTEM",                         info_system_describer,                          info_system_command,                    0);
        repo.register_command(                  L"Query Commands",              L"INFO SERVER",                         info_server_describer,                          info_server_command,                    0);
        repo.register_command(                  L"Query Commands",              L"INFO QUEUES",                         info_queues_describer,                          info_queues_command,                    0);
+       repo.register_command(                  L"Query Commands",              L"INFO THREADS",                        info_threads_describer,                         info_threads_command,                   0);
        repo.register_command(                  L"Query Commands",              L"DIAG",                                        diag_describer,                                         diag_command,                                   0);
        repo.register_command(                  L"Query Commands",              L"BYE",                                         bye_describer,                                          bye_command,                                    0);
        repo.register_command(                  L"Query Commands",              L"KILL",                                        kill_describer,                                         kill_command,                                   0);