<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains the default suppressions for ThreadSanitizer.
// You can also pass additional suppressions via TSAN_OPTIONS:
// TSAN_OPTIONS=suppressions=/path/to/suppressions. Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =
// False positives in libflashplayer.so and libglib.so. Since we don't
// instrument them, we cannot reason about the synchronization in them.
"race:libflashplayer.so\n"
"race:libglib*.so\n"

// Intentional race in ToolsSanityTest.DataRace in base_unittests.
"race:base/tools_sanity_unittest.cc\n"

// Data race on WatchdogCounter [test-only].
"race:base/threading/watchdog_unittest.cc\n"

// Races in libevent, http://crbug.com/23244.
"race:libevent/event.c\n"

// http://crbug.com/46840.
"race:base::HistogramSamples::IncreaseSum\n"
"race:base::Histogram::Add\n"
"race:base::HistogramSamples::Add\n"

// http://crbug.com/84094.
"race:sqlite3StatusSet\n"
"race:pcache1EnforceMaxPage\n"
"race:pcache1AllocPage\n"

// http://crbug.com/102327.
// Test-only race, won't fix.
"race:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup\n"

// http://crbug.com/115540
"race:*GetCurrentThreadIdentifier\n"

// http://crbug.com/120808
"race:base/threading/watchdog.cc\n"

// http://crbug.com/157586
"race:third_party/libvpx/source/libvpx/vp8/decoder/threading.c\n"

// http://crbug.com/158718
"race:third_party/ffmpeg/libavcodec/pthread.c\n"
"race:third_party/ffmpeg/libavcodec/pthread_frame.c\n"
"race:third_party/ffmpeg/libavcodec/vp8.c\n"
"race:third_party/ffmpeg/libavutil/mem.c\n"
"race:*HashFrameForTesting\n"
"race:third_party/ffmpeg/libavcodec/h264pred.c\n"
"race:media::ReleaseData\n"

// http://crbug.com/158922
"race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"
"race:third_party/libvpx/source/libvpx/vp9/encoder/*\n"

// http://crbug.com/189177
"race:thread_manager\n"
"race:v8::Locker::Initialize\n"

// http://crbug.com/239359
"race:media::TestInputCallback::OnData\n"

// http://crbug.com/244368
"race:skia::BeginPlatformPaint\n"

// http://crbug.com/244385
"race:unixTempFileDir\n"

// http://crbug.com/244755
"race:v8::internal::Zone::NewExpand\n"
"race:TooLateToEnableNow\n"
"race:adjust_segment_bytes_allocated\n"

// http://crbug.com/244774
"race:webrtc::RTPReceiver::ProcessBitrate\n"
"race:webrtc::RTPSender::ProcessBitrate\n"
"race:webrtc::VideoCodingModuleImpl::Decode\n"
"race:webrtc::RTPSender::SendOutgoingData\n"
"race:webrtc::VP8EncoderImpl::GetEncodedPartitions\n"
"race:webrtc::VP8EncoderImpl::Encode\n"
"race:webrtc::ViEEncoder::DeliverFrame\n"
"race:webrtc::vcm::VideoReceiver::Decode\n"
"race:webrtc::VCMReceiver::FrameForDecoding\n"
"race:*trace_event_unique_catstatic*\n"

// http://crbug.com/244856
"race:AutoPulseLock\n"

// http://crbug.com/246968
"race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"

// http://crbug.com/246974
"race:content::GpuWatchdogThread::CheckArmed\n"

// http://crbug.com/257396
"race:base::trace_event::"
    "TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"

// http://crbug.com/258479
"race:SamplingStateScope\n"
"race:g_trace_state\n"

// http://crbug.com/258499
"race:third_party/skia/include/core/SkRefCnt.h\n"

// http://crbug.com/268924
"race:base::g_power_monitor\n"
"race:base::PowerMonitor::PowerMonitor\n"
"race:base::PowerMonitor::AddObserver\n"
"race:base::PowerMonitor::RemoveObserver\n"
"race:base::PowerMonitor::IsOnBatteryPower\n"

// http://crbug.com/258935
"race:base::Thread::StopSoon\n"

// http://crbug.com/272095
"race:base::g_top_manager\n"

// http://crbug.com/273047
"race:base::*::g_lazy_tls_ptr\n"
"race:IPC::SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_\n"

// http://crbug.com/280466
"race:content::WebRtcAudioCapturer::SetCapturerSource\n"

// http://crbug.com/285242
"race:media::PulseAudioOutputStream::SetVolume\n"

// http://crbug.com/308590
"race:CustomThreadWatcher::~CustomThreadWatcher\n"

// http://crbug.com/310851
"race:net::ProxyResolverV8Tracing::Job::~Job\n"

// http://crbug.com/313726
"race:CallbackWasCalled\n"

// http://crbug.com/327330
"race:PrepareTextureMailbox\n"
"race:cc::LayerTreeHost::PaintLayerContents\n"

// http://crbug.com/476529
"deadlock:cc::VideoLayerImpl::WillDraw\n"

// http://crbug.com/328826
"race:gLCDOrder\n"
"race:gLCDOrientation\n"

// http://crbug.com/328868
"race:PR_Lock\n"

// http://crbug.com/329225
"race:blink::currentTimeFunction\n"

// http://crbug.com/329460
"race:extensions::InfoMap::AddExtension\n"

// http://crbug.com/333244
"race:content::"
    "VideoCaptureImplTest::MockVideoCaptureImpl::~MockVideoCaptureImpl\n"

// http://crbug.com/333871
"race:v8::internal::Interface::NewValue()::value_interface\n"
"race:v8::internal::IsMinusZero(double)::minus_zero\n"
"race:v8::internal::FastCloneShallowObjectStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::KeyedLoadStubCompiler::registers\n"
"race:v8::internal::KeyedStoreStubCompiler::registers()::registers\n"
"race:v8::internal::KeyedLoadFastElementStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::KeyedStoreFastElementStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::LoadStubCompiler::registers\n"
"race:v8::internal::StoreStubCompiler::registers\n"
"race:v8::internal::HValue::LoopWeight\n"

// http://crbug.com/334140
"race:CommandLine::HasSwitch\n"
"race:CommandLine::current_process_commandline_\n"
"race:CommandLine::GetSwitchValueASCII\n"

// http://crbug.com/338675
"race:blink::s_platform\n"
"race:content::"
    "RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl\n"

// http://crbug.com/345240
"race:WTF::s_shutdown\n"

// http://crbug.com/345245
"race:jingle_glue::JingleThreadWrapper::~JingleThreadWrapper\n"
"race:webrtc::voe::Channel::UpdatePacketDelay\n"
"race:webrtc::voe::Channel::GetDelayEstimate\n"
"race:webrtc::VCMCodecDataBase::DeregisterReceiveCodec\n"
"race:webrtc::GainControlImpl::set_stream_analog_level\n"

// http://crbug.com/345618
"race:WebCore::AudioDestinationNode::render\n"

// http://crbug.com/345624
"race:media::DataSource::set_host\n"

// http://crbug.com/347534
"race:v8::internal::V8::TearDown\n"

// http://crbug.com/347538
"race:sctp_timer_start\n"

// http://crbug.com/347548
"race:cricket::WebRtcVideoMediaChannel::MaybeResetVieSendCodec\n"
"race:cricket::WebRtcVideoMediaChannel::SetSendCodec\n"

// http://crbug.com/347553
"race:blink::WebString::reset\n"

// http://crbug.com/348511
"race:webrtc::acm1::AudioCodingModuleImpl::PlayoutData10Ms\n"

// http://crbug.com/348982
"race:cricket::P2PTransportChannel::OnConnectionDestroyed\n"
"race:cricket::P2PTransportChannel::AddConnection\n"

// http://crbug.com/348984
"race:sctp_express_handle_sack\n"
"race:system_base_info\n"

// http://crbug.com/363999
"race:v8::internal::EnterDebugger::*EnterDebugger\n"

// https://code.google.com/p/v8/issues/detail?id=3143
"race:v8::internal::FLAG_track_double_fields\n"

// https://crbug.com/369257
// TODO(mtklein): annotate properly and remove suppressions.
"race:SandboxIPCHandler::HandleFontMatchRequest\n"
"race:SkFontConfigInterfaceDirect::matchFamilyName\n"
"race:SkFontConfigInterface::GetSingletonDirectInterface\n"
"race:FcStrStaticName\n"

// http://crbug.com/372807
"deadlock:net::X509Certificate::CreateCertificateListFromBytes\n"
"deadlock:net::X509Certificate::CreateFromBytes\n"
"deadlock:net::SSLClientSocketNSS::Core::DoHandshakeLoop\n"

// http://crbug.com/374135
"race:media::AlsaWrapper::PcmWritei\n"

// False positive in libc's tzset_internal, http://crbug.com/379738.
"race:tzset_internal\n"

// http://crbug.com/380554
"deadlock:g_type_add_interface_static\n"

// http:://crbug.com/386385
"race:content::AppCacheStorageImpl::DatabaseTask::CallRunCompleted\n"

// http://crbug.com/388730
"race:g_next_user_script_id\n"

// http://crbug.com/389098
"race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n"

// http://crbug.com/397022
"deadlock:"
"base::trace_event::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"

// http://crbug.com/415472
"deadlock:base::trace_event::TraceLog::GetCategoryGroupEnabled\n"

// http://crbug.com/490856
"deadlock:content::TracingControllerImpl::SetEnabledOnFileThread\n"

// http://crbug.com/417193
// Suppressing both AudioContext.{cpp,h}.
"race:modules/webaudio/AudioContext\n"

// https://code.google.com/p/skia/issues/detail?id=3294
"race:SkBaseMutex::acquire\n"

// https://crbug.com/430533
"race:TileTaskGraphRunner::Run\n"

// https://crbug.com/448203
"race:blink::RemoteFrame::detach\n"

// https://crbug.com/454652
"race:net::NetworkChangeNotifier::SetTestNotificationsOnly\n"

// https://crbug.com/455638
"deadlock:dbus::Bus::ShutdownAndBlock\n"

// https://crbug.com/455665
"race:mojo::common::*::tick_clock\n"
"race:mojo::common::internal::NowTicks\n"

// https://crbug.com/459429
"race:randomnessPid\n"

// https://crbug.com/454655
"race:content::BrowserTestBase::PostTaskToInProcessRendererAndWait\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<commit_msg>Suppress the race on OPENSSL_ia32cap_P[] (issue 512783)<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains the default suppressions for ThreadSanitizer.
// You can also pass additional suppressions via TSAN_OPTIONS:
// TSAN_OPTIONS=suppressions=/path/to/suppressions. Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =
// False positives in libflashplayer.so and libglib.so. Since we don't
// instrument them, we cannot reason about the synchronization in them.
"race:libflashplayer.so\n"
"race:libglib*.so\n"

// Intentional race in ToolsSanityTest.DataRace in base_unittests.
"race:base/tools_sanity_unittest.cc\n"

// Data race on WatchdogCounter [test-only].
"race:base/threading/watchdog_unittest.cc\n"

// Races in libevent, http://crbug.com/23244.
"race:libevent/event.c\n"

// http://crbug.com/46840.
"race:base::HistogramSamples::IncreaseSum\n"
"race:base::Histogram::Add\n"
"race:base::HistogramSamples::Add\n"

// http://crbug.com/84094.
"race:sqlite3StatusSet\n"
"race:pcache1EnforceMaxPage\n"
"race:pcache1AllocPage\n"

// http://crbug.com/102327.
// Test-only race, won't fix.
"race:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup\n"

// http://crbug.com/115540
"race:*GetCurrentThreadIdentifier\n"

// http://crbug.com/120808
"race:base/threading/watchdog.cc\n"

// http://crbug.com/157586
"race:third_party/libvpx/source/libvpx/vp8/decoder/threading.c\n"

// http://crbug.com/158718
"race:third_party/ffmpeg/libavcodec/pthread.c\n"
"race:third_party/ffmpeg/libavcodec/pthread_frame.c\n"
"race:third_party/ffmpeg/libavcodec/vp8.c\n"
"race:third_party/ffmpeg/libavutil/mem.c\n"
"race:*HashFrameForTesting\n"
"race:third_party/ffmpeg/libavcodec/h264pred.c\n"
"race:media::ReleaseData\n"

// http://crbug.com/158922
"race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"
"race:third_party/libvpx/source/libvpx/vp9/encoder/*\n"

// http://crbug.com/189177
"race:thread_manager\n"
"race:v8::Locker::Initialize\n"

// http://crbug.com/239359
"race:media::TestInputCallback::OnData\n"

// http://crbug.com/244368
"race:skia::BeginPlatformPaint\n"

// http://crbug.com/244385
"race:unixTempFileDir\n"

// http://crbug.com/244755
"race:v8::internal::Zone::NewExpand\n"
"race:TooLateToEnableNow\n"
"race:adjust_segment_bytes_allocated\n"

// http://crbug.com/244774
"race:webrtc::RTPReceiver::ProcessBitrate\n"
"race:webrtc::RTPSender::ProcessBitrate\n"
"race:webrtc::VideoCodingModuleImpl::Decode\n"
"race:webrtc::RTPSender::SendOutgoingData\n"
"race:webrtc::VP8EncoderImpl::GetEncodedPartitions\n"
"race:webrtc::VP8EncoderImpl::Encode\n"
"race:webrtc::ViEEncoder::DeliverFrame\n"
"race:webrtc::vcm::VideoReceiver::Decode\n"
"race:webrtc::VCMReceiver::FrameForDecoding\n"
"race:*trace_event_unique_catstatic*\n"

// http://crbug.com/244856
"race:AutoPulseLock\n"

// http://crbug.com/246968
"race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"

// http://crbug.com/246974
"race:content::GpuWatchdogThread::CheckArmed\n"

// http://crbug.com/257396
"race:base::trace_event::"
    "TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"

// http://crbug.com/258479
"race:SamplingStateScope\n"
"race:g_trace_state\n"

// http://crbug.com/258499
"race:third_party/skia/include/core/SkRefCnt.h\n"

// http://crbug.com/268924
"race:base::g_power_monitor\n"
"race:base::PowerMonitor::PowerMonitor\n"
"race:base::PowerMonitor::AddObserver\n"
"race:base::PowerMonitor::RemoveObserver\n"
"race:base::PowerMonitor::IsOnBatteryPower\n"

// http://crbug.com/258935
"race:base::Thread::StopSoon\n"

// http://crbug.com/272095
"race:base::g_top_manager\n"

// http://crbug.com/273047
"race:base::*::g_lazy_tls_ptr\n"
"race:IPC::SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_\n"

// http://crbug.com/280466
"race:content::WebRtcAudioCapturer::SetCapturerSource\n"

// http://crbug.com/285242
"race:media::PulseAudioOutputStream::SetVolume\n"

// http://crbug.com/308590
"race:CustomThreadWatcher::~CustomThreadWatcher\n"

// http://crbug.com/310851
"race:net::ProxyResolverV8Tracing::Job::~Job\n"

// http://crbug.com/313726
"race:CallbackWasCalled\n"

// http://crbug.com/327330
"race:PrepareTextureMailbox\n"
"race:cc::LayerTreeHost::PaintLayerContents\n"

// http://crbug.com/476529
"deadlock:cc::VideoLayerImpl::WillDraw\n"

// http://crbug.com/328826
"race:gLCDOrder\n"
"race:gLCDOrientation\n"

// http://crbug.com/328868
"race:PR_Lock\n"

// http://crbug.com/329225
"race:blink::currentTimeFunction\n"

// http://crbug.com/329460
"race:extensions::InfoMap::AddExtension\n"

// http://crbug.com/333244
"race:content::"
    "VideoCaptureImplTest::MockVideoCaptureImpl::~MockVideoCaptureImpl\n"

// http://crbug.com/333871
"race:v8::internal::Interface::NewValue()::value_interface\n"
"race:v8::internal::IsMinusZero(double)::minus_zero\n"
"race:v8::internal::FastCloneShallowObjectStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::KeyedLoadStubCompiler::registers\n"
"race:v8::internal::KeyedStoreStubCompiler::registers()::registers\n"
"race:v8::internal::KeyedLoadFastElementStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::KeyedStoreFastElementStub::InitializeInterfaceDescriptor\n"
"race:v8::internal::LoadStubCompiler::registers\n"
"race:v8::internal::StoreStubCompiler::registers\n"
"race:v8::internal::HValue::LoopWeight\n"

// http://crbug.com/334140
"race:CommandLine::HasSwitch\n"
"race:CommandLine::current_process_commandline_\n"
"race:CommandLine::GetSwitchValueASCII\n"

// http://crbug.com/338675
"race:blink::s_platform\n"
"race:content::"
    "RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl\n"

// http://crbug.com/345240
"race:WTF::s_shutdown\n"

// http://crbug.com/345245
"race:jingle_glue::JingleThreadWrapper::~JingleThreadWrapper\n"
"race:webrtc::voe::Channel::UpdatePacketDelay\n"
"race:webrtc::voe::Channel::GetDelayEstimate\n"
"race:webrtc::VCMCodecDataBase::DeregisterReceiveCodec\n"
"race:webrtc::GainControlImpl::set_stream_analog_level\n"

// http://crbug.com/345618
"race:WebCore::AudioDestinationNode::render\n"

// http://crbug.com/345624
"race:media::DataSource::set_host\n"

// http://crbug.com/347534
"race:v8::internal::V8::TearDown\n"

// http://crbug.com/347538
"race:sctp_timer_start\n"

// http://crbug.com/347548
"race:cricket::WebRtcVideoMediaChannel::MaybeResetVieSendCodec\n"
"race:cricket::WebRtcVideoMediaChannel::SetSendCodec\n"

// http://crbug.com/347553
"race:blink::WebString::reset\n"

// http://crbug.com/348511
"race:webrtc::acm1::AudioCodingModuleImpl::PlayoutData10Ms\n"

// http://crbug.com/348982
"race:cricket::P2PTransportChannel::OnConnectionDestroyed\n"
"race:cricket::P2PTransportChannel::AddConnection\n"

// http://crbug.com/348984
"race:sctp_express_handle_sack\n"
"race:system_base_info\n"

// http://crbug.com/363999
"race:v8::internal::EnterDebugger::*EnterDebugger\n"

// https://code.google.com/p/v8/issues/detail?id=3143
"race:v8::internal::FLAG_track_double_fields\n"

// https://crbug.com/369257
// TODO(mtklein): annotate properly and remove suppressions.
"race:SandboxIPCHandler::HandleFontMatchRequest\n"
"race:SkFontConfigInterfaceDirect::matchFamilyName\n"
"race:SkFontConfigInterface::GetSingletonDirectInterface\n"
"race:FcStrStaticName\n"

// http://crbug.com/372807
"deadlock:net::X509Certificate::CreateCertificateListFromBytes\n"
"deadlock:net::X509Certificate::CreateFromBytes\n"
"deadlock:net::SSLClientSocketNSS::Core::DoHandshakeLoop\n"

// http://crbug.com/374135
"race:media::AlsaWrapper::PcmWritei\n"

// False positive in libc's tzset_internal, http://crbug.com/379738.
"race:tzset_internal\n"

// http://crbug.com/380554
"deadlock:g_type_add_interface_static\n"

// http:://crbug.com/386385
"race:content::AppCacheStorageImpl::DatabaseTask::CallRunCompleted\n"

// http://crbug.com/388730
"race:g_next_user_script_id\n"

// http://crbug.com/389098
"race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n"

// http://crbug.com/397022
"deadlock:"
"base::trace_event::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"

// http://crbug.com/415472
"deadlock:base::trace_event::TraceLog::GetCategoryGroupEnabled\n"

// http://crbug.com/490856
"deadlock:content::TracingControllerImpl::SetEnabledOnFileThread\n"

// http://crbug.com/417193
// Suppressing both AudioContext.{cpp,h}.
"race:modules/webaudio/AudioContext\n"

// https://code.google.com/p/skia/issues/detail?id=3294
"race:SkBaseMutex::acquire\n"

// https://crbug.com/430533
"race:TileTaskGraphRunner::Run\n"

// https://crbug.com/448203
"race:blink::RemoteFrame::detach\n"

// https://crbug.com/454652
"race:net::NetworkChangeNotifier::SetTestNotificationsOnly\n"

// https://crbug.com/455638
"deadlock:dbus::Bus::ShutdownAndBlock\n"

// https://crbug.com/455665
"race:mojo::common::*::tick_clock\n"
"race:mojo::common::internal::NowTicks\n"

// https://crbug.com/459429
"race:randomnessPid\n"

// https://crbug.com/454655
"race:content::BrowserTestBase::PostTaskToInProcessRendererAndWait\n"

// https://crbug.com/512783
"race:OPENSSL_ia32cap_P\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<|endoftext|>


<commit_before>// Copyright 2015, Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>

#include <algorithm>

// This program attempts to pick sets of memory locations that map to
// the same L3 cache set.  It tests whether they really do map to the
// same cache set by timing accesses to them and outputting a CSV file
// of times that can be graphed.  This program assumes a 2-core Sandy
// Bridge CPU.

// Dummy variable to attempt to prevent compiler and CPU from skipping
// memory accesses.
int g_dummy;

namespace {

const int page_size = 0x1000;
int g_pagemap_fd = -1;

// Extract the physical page number from a Linux /proc/PID/pagemap entry.
uint64_t frame_number_from_pagemap(uint64_t value) {
  return value & ((1ULL << 54) - 1);
}

void init_pagemap() {
  g_pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
  assert(g_pagemap_fd >= 0);
}

uint64_t get_physical_addr(uintptr_t virtual_addr) {
  uint64_t value;
  off_t offset = (virtual_addr / page_size) * sizeof(value);
  int got = pread(g_pagemap_fd, &value, sizeof(value), offset);
  assert(got == 8);

  // Check the "page present" flag.
  assert(value & (1ULL << 63));

  uint64_t frame_num = frame_number_from_pagemap(value);
  return (frame_num * page_size) | (virtual_addr & (page_size - 1));
}

// Execute a CPU memory barrier.  This is an attempt to prevent memory
// accesses from being reordered, in case reordering affects what gets
// evicted from the cache.  It's also an attempt to ensure we're
// measuring the time for a single memory access.
//
// However, this appears to be unnecessary on Sandy Bridge CPUs, since
// we get the same shape graph without this.
inline void mfence() {
  asm volatile("mfence");
}

// Measure the time taken to access the given address, in nanoseconds.
int time_access(uintptr_t ptr) {
  struct timespec ts0;
  int rc = clock_gettime(CLOCK_MONOTONIC, &ts0);
  assert(rc == 0);

  g_dummy += *(volatile int *) ptr;
  mfence();

  struct timespec ts;
  rc = clock_gettime(CLOCK_MONOTONIC, &ts);
  assert(rc == 0);
  return (ts.tv_sec - ts0.tv_sec) * 1000000000
         + (ts.tv_nsec - ts0.tv_nsec);
}

// Given a physical memory address, this hashes the address and
// returns the number of the cache slice that the address maps to.
//
// This assumes a 2-core Sandy Bridge CPU.
int get_cache_slice(uint64_t phys_addr) {
  // On a 4-core machine, the CPU's hash function produces a 2-bit
  // cache slice number, where the two bits are defined by "h1" and
  // "h2":
  //
  // h1 function:
  //   static const int bits[] = { 18, 19, 21, 23, 25, 27, 29, 30, 31 };
  // h2 function:
  //   static const int bits[] = { 17, 19, 20, 21, 22, 23, 24, 26, 28, 29, 31 };
  //
  // This hash function is described in the paper "Practical Timing
  // Side Channel Attacks Against Kernel Space ASLR".
  //
  // On a 2-core machine, the CPU's hash function produces a 1-bit
  // cache slice number which appears to be the XOR of h1 and h2.

  // XOR of h1 and h2:
  static const int bits[] = { 17, 18, 20, 22, 24, 25, 26, 27, 28, 30 };

  int count = sizeof(bits) / sizeof(bits[0]);
  int hash = 0;
  for (int i = 0; i < count; i++) {
    hash ^= (phys_addr >> bits[i]) & 1;
  }
  return hash;
}

uint32_t get_cache_set(uint64_t phys) {
  // For Sandy Bridge, the bottom 17 bits determine the cache set
  // within the cache slice (or the location within a cache line).
  int bits = 17 - 6;
  uint32_t bottom_part = (phys >> 6) & ((1 << bits) - 1);
  return bottom_part | (get_cache_slice(phys) << bits);
}

bool in_same_cache_set(uint64_t phys1, uint64_t phys2) {
  return get_cache_set(phys1) == get_cache_set(phys2);
}

int timing(int addr_count) {
  size_t size = 16 << 20;
  uintptr_t buf =
    (uintptr_t) mmap(NULL, size, PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
  assert(buf);

  uintptr_t addrs[addr_count];
  addrs[0] = buf;
  uintptr_t phys1 = get_physical_addr(addrs[0]);

  // Pick a set of addresses which we think belong to the same cache set.
  uintptr_t next_addr = buf + page_size;
  uintptr_t end_addr = buf + size;
  int found = 1;
  while (found < addr_count) {
    assert(next_addr < end_addr);
    uintptr_t addr = next_addr;
    next_addr += page_size;

    uint64_t phys2 = get_physical_addr(addr);
    if (in_same_cache_set(phys1, phys2)) {
      addrs[found] = addr;
      found++;
    }
  }

  // Time memory accesses.
  int runs = 10;
  int times[runs];
  for (int run = 0; run < runs; run++) {
    // Ensure the first address is cached by accessing it.
    g_dummy += *(volatile int *) addrs[0];
    mfence();
    // Now pull the other addresses through the cache too.
    for (int i = 1; i < addr_count; i++) {
      g_dummy += *(volatile int *) addrs[i];
    }
    mfence();
    // See whether the first address got evicted from the cache by
    // timing accessing it.
    times[run] = time_access(addrs[0]);
  }
  // Find the median time.  We use the median in order to discard
  // outliers.  We want to discard outlying slow results which are
  // likely to be the result of other activity on the machine.
  //
  // We also want to discard outliers where memory was accessed
  // unusually quickly.  These could be the result of the CPU's
  // eviction policy not using an exact LRU policy.
  std::sort(times, &times[runs]);
  int median_time = times[runs / 2];

  int rc = munmap((void *) buf, size);
  assert(rc == 0);

  return median_time;
}

int timing_mean(int addr_count) {
  int runs = 10;
  int sum_time = 0;
  for (int i = 0; i < runs; i++)
    sum_time += timing(addr_count);
  return sum_time / runs;
}

} // namespace

int main() {
  init_pagemap();

  // Turn off stdout caching.
  setvbuf(stdout, NULL, _IONBF, 0);

  // For a 12-way cache, we want to pick 13 addresses belonging to the
  // same cache set.  Measure the effect of picking more addresses to
  // test whether in_same_cache_set() is correctly determining whether
  // addresses belong to the same cache set.
  int max_addr_count = 13 * 4;

  printf("Address count,Time (ns)\n");

  for (int addr_count = 0; addr_count < max_addr_count; addr_count++) {
    printf("%i,%i\n", addr_count, timing_mean(addr_count));
  }
  return 0;
}
<commit_msg>Cache analysis: Refactor address finding logic into a class<commit_after>// Copyright 2015, Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>

#include <algorithm>

// This program attempts to pick sets of memory locations that map to
// the same L3 cache set.  It tests whether they really do map to the
// same cache set by timing accesses to them and outputting a CSV file
// of times that can be graphed.  This program assumes a 2-core Sandy
// Bridge CPU.

// Dummy variable to attempt to prevent compiler and CPU from skipping
// memory accesses.
int g_dummy;

namespace {

const int page_size = 0x1000;
int g_pagemap_fd = -1;

// Extract the physical page number from a Linux /proc/PID/pagemap entry.
uint64_t frame_number_from_pagemap(uint64_t value) {
  return value & ((1ULL << 54) - 1);
}

void init_pagemap() {
  g_pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
  assert(g_pagemap_fd >= 0);
}

uint64_t get_physical_addr(uintptr_t virtual_addr) {
  uint64_t value;
  off_t offset = (virtual_addr / page_size) * sizeof(value);
  int got = pread(g_pagemap_fd, &value, sizeof(value), offset);
  assert(got == 8);

  // Check the "page present" flag.
  assert(value & (1ULL << 63));

  uint64_t frame_num = frame_number_from_pagemap(value);
  return (frame_num * page_size) | (virtual_addr & (page_size - 1));
}

// Execute a CPU memory barrier.  This is an attempt to prevent memory
// accesses from being reordered, in case reordering affects what gets
// evicted from the cache.  It's also an attempt to ensure we're
// measuring the time for a single memory access.
//
// However, this appears to be unnecessary on Sandy Bridge CPUs, since
// we get the same shape graph without this.
inline void mfence() {
  asm volatile("mfence");
}

// Measure the time taken to access the given address, in nanoseconds.
int time_access(uintptr_t ptr) {
  struct timespec ts0;
  int rc = clock_gettime(CLOCK_MONOTONIC, &ts0);
  assert(rc == 0);

  g_dummy += *(volatile int *) ptr;
  mfence();

  struct timespec ts;
  rc = clock_gettime(CLOCK_MONOTONIC, &ts);
  assert(rc == 0);
  return (ts.tv_sec - ts0.tv_sec) * 1000000000
         + (ts.tv_nsec - ts0.tv_nsec);
}

// Given a physical memory address, this hashes the address and
// returns the number of the cache slice that the address maps to.
//
// This assumes a 2-core Sandy Bridge CPU.
int get_cache_slice(uint64_t phys_addr) {
  // On a 4-core machine, the CPU's hash function produces a 2-bit
  // cache slice number, where the two bits are defined by "h1" and
  // "h2":
  //
  // h1 function:
  //   static const int bits[] = { 18, 19, 21, 23, 25, 27, 29, 30, 31 };
  // h2 function:
  //   static const int bits[] = { 17, 19, 20, 21, 22, 23, 24, 26, 28, 29, 31 };
  //
  // This hash function is described in the paper "Practical Timing
  // Side Channel Attacks Against Kernel Space ASLR".
  //
  // On a 2-core machine, the CPU's hash function produces a 1-bit
  // cache slice number which appears to be the XOR of h1 and h2.

  // XOR of h1 and h2:
  static const int bits[] = { 17, 18, 20, 22, 24, 25, 26, 27, 28, 30 };

  int count = sizeof(bits) / sizeof(bits[0]);
  int hash = 0;
  for (int i = 0; i < count; i++) {
    hash ^= (phys_addr >> bits[i]) & 1;
  }
  return hash;
}

uint32_t get_cache_set(uint64_t phys) {
  // For Sandy Bridge, the bottom 17 bits determine the cache set
  // within the cache slice (or the location within a cache line).
  int bits = 17 - 6;
  uint32_t bottom_part = (phys >> 6) & ((1 << bits) - 1);
  return bottom_part | (get_cache_slice(phys) << bits);
}

bool in_same_cache_set(uint64_t phys1, uint64_t phys2) {
  return get_cache_set(phys1) == get_cache_set(phys2);
}

class AddrFinder {
  static const size_t size = 16 << 20;
  uintptr_t buf_;

 public:
  AddrFinder() {
    buf_ = (uintptr_t) mmap(NULL, size, PROT_READ | PROT_WRITE,
                            MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
    assert(buf_ != (uintptr_t) MAP_FAILED);
  }

  ~AddrFinder() {
    int rc = munmap((void *) buf_, size);
    assert(rc == 0);
  }

  // Pick a set of addresses which we think belong to the same cache set.
  void get_set(uintptr_t *addrs, int addr_count) {
    addrs[0] = buf_;
    uint32_t cache_set = get_cache_set(get_physical_addr(addrs[0]));

    uintptr_t next_addr = buf_ + page_size;
    uintptr_t end_addr = buf_ + size;
    int found = 1;
    while (found < addr_count) {
      assert(next_addr < end_addr);
      uintptr_t addr = next_addr;
      next_addr += page_size;

      if (get_cache_set(get_physical_addr(addr)) == cache_set) {
        addrs[found++] = addr;
      }
    }
  }
};

int timing(int addr_count) {
  AddrFinder finder;
  uintptr_t addrs[addr_count];
  finder.get_set(addrs, addr_count);

  // Time memory accesses.
  int runs = 10;
  int times[runs];
  for (int run = 0; run < runs; run++) {
    // Ensure the first address is cached by accessing it.
    g_dummy += *(volatile int *) addrs[0];
    mfence();
    // Now pull the other addresses through the cache too.
    for (int i = 1; i < addr_count; i++) {
      g_dummy += *(volatile int *) addrs[i];
    }
    mfence();
    // See whether the first address got evicted from the cache by
    // timing accessing it.
    times[run] = time_access(addrs[0]);
  }
  // Find the median time.  We use the median in order to discard
  // outliers.  We want to discard outlying slow results which are
  // likely to be the result of other activity on the machine.
  //
  // We also want to discard outliers where memory was accessed
  // unusually quickly.  These could be the result of the CPU's
  // eviction policy not using an exact LRU policy.
  std::sort(times, &times[runs]);
  int median_time = times[runs / 2];

  return median_time;
}

int timing_mean(int addr_count) {
  int runs = 10;
  int sum_time = 0;
  for (int i = 0; i < runs; i++)
    sum_time += timing(addr_count);
  return sum_time / runs;
}

} // namespace

int main() {
  init_pagemap();

  // Turn off stdout caching.
  setvbuf(stdout, NULL, _IONBF, 0);

  // For a 12-way cache, we want to pick 13 addresses belonging to the
  // same cache set.  Measure the effect of picking more addresses to
  // test whether in_same_cache_set() is correctly determining whether
  // addresses belong to the same cache set.
  int max_addr_count = 13 * 4;

  printf("Address count,Time (ns)\n");

  for (int addr_count = 0; addr_count < max_addr_count; addr_count++) {
    printf("%i,%i\n", addr_count, timing_mean(addr_count));
  }
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS mergebuild (1.2.88); FILE MERGED 2004/05/28 18:57:38 hjs 1.2.88.2: RESYNC: (1.2-1.3); FILE MERGED 2004/01/29 15:45:09 hjs 1.2.88.1: #i8252# chng. resmgr creation parameters from LanguageType to ::com::sun::star::lang::Locale<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <concepts>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "bytes.hh"

enum class mutable_view { no, yes, };

/// Fragmented buffer
///
/// Concept `FragmentedBuffer` is satisfied by any class that is a range of
/// fragments and provides a method `size_bytes()` which returns the total
/// size of the buffer. The interfaces accepting `FragmentedBuffer` will attempt
/// to avoid unnecessary linearisation.
template<typename T>
concept FragmentRange = requires (T range) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
        || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    { *range.begin() } -> std::convertible_to<const typename T::fragment_type&>;
    { *range.end() } -> std::convertible_to<const typename T::fragment_type&>;
    { range.size_bytes() } -> std::convertible_to<size_t>;
    { range.empty() } -> std::same_as<bool>; // returns true iff size_bytes() == 0.
};

template<typename T, typename = void>
struct is_fragment_range : std::false_type { };

template<typename T>
struct is_fragment_range<T, std::void_t<typename T::fragment_type>> : std::true_type { };

template<typename T>
static constexpr bool is_fragment_range_v = is_fragment_range<T>::value;

/// A non-mutable view of a FragmentRange
///
/// Provide a trivially copyable and movable, non-mutable view on a
/// fragment range. This allows uniform ownership semantics across
/// multi-fragment ranges and the single fragment and empty fragment
/// adaptors below, i.e. it allows treating all fragment ranges
/// uniformly as views.
template <typename T>
requires FragmentRange<T>
class fragment_range_view {
    const T* _range;
public:
    using fragment_type = typename T::fragment_type;
    using iterator = typename T::const_iterator;
    using const_iterator = typename T::const_iterator;

public:
    explicit fragment_range_view(const T& range) : _range(&range) { }

    const_iterator begin() const { return _range->begin(); }
    const_iterator end() const { return _range->end(); }

    size_t size_bytes() const { return _range->size_bytes(); }
    bool empty() const { return _range->empty(); }
};

/// Single-element fragment range
///
/// This is a helper that allows converting a bytes_view into a FragmentRange.
template<mutable_view is_mutable>
class single_fragment_range {
public:
    using fragment_type = std::conditional_t<is_mutable == mutable_view::no,
                                             bytes_view, bytes_mutable_view>;
private:
    fragment_type _view;
public:
    using iterator = const fragment_type*;
    using const_iterator = const fragment_type*;

    explicit single_fragment_range(fragment_type f) : _view { f } { }

    const_iterator begin() const { return &_view; }
    const_iterator end() const { return &_view + 1; }

    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
};

single_fragment_range(bytes_view) -> single_fragment_range<mutable_view::no>;
single_fragment_range(bytes_mutable_view) -> single_fragment_range<mutable_view::yes>;

/// Empty fragment range.
struct empty_fragment_range {
    using fragment_type = bytes_view;
    using iterator = bytes_view*;
    using const_iterator = bytes_view*;

    iterator begin() const { return nullptr; }
    iterator end() const { return nullptr; }

    size_t size_bytes() const { return 0; }
    bool empty() const { return true; }
};

static_assert(FragmentRange<empty_fragment_range>);
static_assert(FragmentRange<single_fragment_range<mutable_view::no>>);
static_assert(FragmentRange<single_fragment_range<mutable_view::yes>>);

template<typename FragmentedBuffer>
requires FragmentRange<FragmentedBuffer>
bytes linearized(const FragmentedBuffer& buffer)
{
    bytes b(bytes::initialized_later(), buffer.size_bytes());
    auto dst = b.begin();
    using boost::range::for_each;
    for_each(buffer, [&] (bytes_view fragment) {
        dst = boost::copy(fragment, dst);
    });
    return b;
}

template<typename FragmentedBuffer, typename Function>
requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
    fn(bv);
}
decltype(auto) with_linearized(const FragmentedBuffer& buffer, Function&& fn)
{
    bytes b;
    bytes_view bv;
    if (__builtin_expect(!buffer.empty() && std::next(buffer.begin()) == buffer.end(), true)) {
        bv = *buffer.begin();
    } else if (!buffer.empty()) {
        b = linearized(buffer);
        bv = b;
    }
    return fn(bv);
}

template<typename T>
concept FragmentedView = requires (T view, size_t n) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
            || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    // No preconditions.
    { view.current_fragment() } -> std::convertible_to<const typename T::fragment_type&>;
    // No preconditions.
    { view.size_bytes() } -> std::convertible_to<size_t>;
    // Precondition: n <= size_bytes()
    { view.prefix(n) } -> std::same_as<T>;
    // Precondition: n <= size_bytes()
    view.remove_prefix(n);
    // Precondition: size_bytes() > 0
    view.remove_current();
};

template<typename T>
concept FragmentedMutableView = requires (T view) {
    requires FragmentedView<T>;
    requires std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
};

template<FragmentedView View>
requires (!FragmentRange<View>)
bytes linearized(View v)
{
    bytes b(bytes::initialized_later(), v.size_bytes());
    auto out = b.begin();
    while (v.size_bytes()) {
        out = std::copy(v.current_fragment().begin(), v.current_fragment().end(), out);
        v.remove_current();
    }
    return b;
}

template<FragmentedView View, typename Function>
requires (!FragmentRange<View>) && std::invocable<Function, bytes_view>
decltype(auto) with_linearized(const View& v, Function&& fn)
{
    if (v.size_bytes() == v.current_fragment().size()) [[likely]] {
        return fn(v.current_fragment());
    } else {
        return fn(linearized(v));
    }
}
<commit_msg>utils: fragment_range: add single_fragmented_view<commit_after>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <concepts>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "bytes.hh"

enum class mutable_view { no, yes, };

/// Fragmented buffer
///
/// Concept `FragmentedBuffer` is satisfied by any class that is a range of
/// fragments and provides a method `size_bytes()` which returns the total
/// size of the buffer. The interfaces accepting `FragmentedBuffer` will attempt
/// to avoid unnecessary linearisation.
template<typename T>
concept FragmentRange = requires (T range) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
        || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    { *range.begin() } -> std::convertible_to<const typename T::fragment_type&>;
    { *range.end() } -> std::convertible_to<const typename T::fragment_type&>;
    { range.size_bytes() } -> std::convertible_to<size_t>;
    { range.empty() } -> std::same_as<bool>; // returns true iff size_bytes() == 0.
};

template<typename T, typename = void>
struct is_fragment_range : std::false_type { };

template<typename T>
struct is_fragment_range<T, std::void_t<typename T::fragment_type>> : std::true_type { };

template<typename T>
static constexpr bool is_fragment_range_v = is_fragment_range<T>::value;

/// A non-mutable view of a FragmentRange
///
/// Provide a trivially copyable and movable, non-mutable view on a
/// fragment range. This allows uniform ownership semantics across
/// multi-fragment ranges and the single fragment and empty fragment
/// adaptors below, i.e. it allows treating all fragment ranges
/// uniformly as views.
template <typename T>
requires FragmentRange<T>
class fragment_range_view {
    const T* _range;
public:
    using fragment_type = typename T::fragment_type;
    using iterator = typename T::const_iterator;
    using const_iterator = typename T::const_iterator;

public:
    explicit fragment_range_view(const T& range) : _range(&range) { }

    const_iterator begin() const { return _range->begin(); }
    const_iterator end() const { return _range->end(); }

    size_t size_bytes() const { return _range->size_bytes(); }
    bool empty() const { return _range->empty(); }
};

/// Single-element fragment range
///
/// This is a helper that allows converting a bytes_view into a FragmentRange.
template<mutable_view is_mutable>
class single_fragment_range {
public:
    using fragment_type = std::conditional_t<is_mutable == mutable_view::no,
                                             bytes_view, bytes_mutable_view>;
private:
    fragment_type _view;
public:
    using iterator = const fragment_type*;
    using const_iterator = const fragment_type*;

    explicit single_fragment_range(fragment_type f) : _view { f } { }

    const_iterator begin() const { return &_view; }
    const_iterator end() const { return &_view + 1; }

    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
};

single_fragment_range(bytes_view) -> single_fragment_range<mutable_view::no>;
single_fragment_range(bytes_mutable_view) -> single_fragment_range<mutable_view::yes>;

/// Empty fragment range.
struct empty_fragment_range {
    using fragment_type = bytes_view;
    using iterator = bytes_view*;
    using const_iterator = bytes_view*;

    iterator begin() const { return nullptr; }
    iterator end() const { return nullptr; }

    size_t size_bytes() const { return 0; }
    bool empty() const { return true; }
};

static_assert(FragmentRange<empty_fragment_range>);
static_assert(FragmentRange<single_fragment_range<mutable_view::no>>);
static_assert(FragmentRange<single_fragment_range<mutable_view::yes>>);

template<typename FragmentedBuffer>
requires FragmentRange<FragmentedBuffer>
bytes linearized(const FragmentedBuffer& buffer)
{
    bytes b(bytes::initialized_later(), buffer.size_bytes());
    auto dst = b.begin();
    using boost::range::for_each;
    for_each(buffer, [&] (bytes_view fragment) {
        dst = boost::copy(fragment, dst);
    });
    return b;
}

template<typename FragmentedBuffer, typename Function>
requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
    fn(bv);
}
decltype(auto) with_linearized(const FragmentedBuffer& buffer, Function&& fn)
{
    bytes b;
    bytes_view bv;
    if (__builtin_expect(!buffer.empty() && std::next(buffer.begin()) == buffer.end(), true)) {
        bv = *buffer.begin();
    } else if (!buffer.empty()) {
        b = linearized(buffer);
        bv = b;
    }
    return fn(bv);
}

template<typename T>
concept FragmentedView = requires (T view, size_t n) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
            || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    // No preconditions.
    { view.current_fragment() } -> std::convertible_to<const typename T::fragment_type&>;
    // No preconditions.
    { view.size_bytes() } -> std::convertible_to<size_t>;
    // Precondition: n <= size_bytes()
    { view.prefix(n) } -> std::same_as<T>;
    // Precondition: n <= size_bytes()
    view.remove_prefix(n);
    // Precondition: size_bytes() > 0
    view.remove_current();
};

template<typename T>
concept FragmentedMutableView = requires (T view) {
    requires FragmentedView<T>;
    requires std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
};

template<FragmentedView View>
requires (!FragmentRange<View>)
bytes linearized(View v)
{
    bytes b(bytes::initialized_later(), v.size_bytes());
    auto out = b.begin();
    while (v.size_bytes()) {
        out = std::copy(v.current_fragment().begin(), v.current_fragment().end(), out);
        v.remove_current();
    }
    return b;
}

template<FragmentedView View, typename Function>
requires (!FragmentRange<View>) && std::invocable<Function, bytes_view>
decltype(auto) with_linearized(const View& v, Function&& fn)
{
    if (v.size_bytes() == v.current_fragment().size()) [[likely]] {
        return fn(v.current_fragment());
    } else {
        return fn(linearized(v));
    }
}

class single_fragmented_view {
    bytes_view _view;
public:
    using fragment_type = bytes_view;
    explicit single_fragmented_view(bytes_view bv) : _view(bv) {}
    size_t size_bytes() const { return _view.size(); }
    void remove_prefix(size_t n) { _view.remove_prefix(n); }
    void remove_current() { _view = bytes_view(); }
    bytes_view current_fragment() const { return _view; }
    single_fragmented_view prefix(size_t n) { return single_fragmented_view(_view.substr(0, n)); }
};
static_assert(FragmentedView<single_fragmented_view>);
<|endoftext|>


<commit_before>/*
 * This file is part of the KGLEngine2D project.
 * Copyright (C) 2008 Sacha Schutz <istdasklar@free.fr>
 * Copyright (C) 2008 Olivier Gueudelot <gueudelotolive@gmail.com>
 * Copyright (C) 2008 Charles Huet <packadal@gmail.com>
 *
 * This program 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 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <KApplication>
#include <KAboutData>
#include <KCmdLineArgs>
#include <KDebug>
#include <QWidget>
#include <gluon/kgl/kglview.h>
#include <gluon/kgl/kglengine.h>
#include <gluon/kgl/kglboxitem.h>
#include <gluon/kgl/kglparticlesitem.h>
using namespace std;

int main(int argc, char *argv[])
{
    KAboutData aboutData("kgl_tutorial2", 0,
                         ki18n("gluon"), "1.0",
                         ki18n("gluon"),
                         KAboutData::License_GPL,
                         ki18n("Copyright (c) 2009 Developer"));
    KCmdLineArgs::init(argc, argv, &aboutData);

    KApplication app;

    KGLEngine * engine = new KGLEngine;
    KGLView * view = new KGLView(engine);

    KGLParticlesItem * explose = new KGLParticlesItem;
    explose->createSmoke(40,KIcon("kgl").pixmap(32,32),45,0.07,0.003,32);
    engine->addItem(explose);
    explose->setPosition(-10,-10);
    explose->setAngle(0);
    explose->updateTransform();

    KGLParticlesItem * explose2 = new KGLParticlesItem;
    explose2->createSmoke(40,KIcon("kal").pixmap(32,32),45,0.07,0.003,32);
    engine->addItem(explose2);
    explose2->setAngle(180);
    explose2->setPosition(10,10);
    explose2->updateTransform();

    KGLParticlesItem * gluon = new KGLParticlesItem;
    gluon->createExplose(40,KIcon("gluon").pixmap(32,32),360,0.1,0.01,25);
    engine->addItem(gluon);

    view->start();
    view->show();
    app.exec();

}
<commit_msg>add KIcon header<commit_after>/*
 * This file is part of the KGLEngine2D project.
 * Copyright (C) 2008 Sacha Schutz <istdasklar@free.fr>
 * Copyright (C) 2008 Olivier Gueudelot <gueudelotolive@gmail.com>
 * Copyright (C) 2008 Charles Huet <packadal@gmail.com>
 *
 * This program 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 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <KApplication>
#include <KAboutData>
#include <KCmdLineArgs>
#include <KDebug>
#include <QWidget>
#include <KIcon>
#include <gluon/kgl/kglview.h>
#include <gluon/kgl/kglengine.h>
#include <gluon/kgl/kglboxitem.h>
#include <gluon/kgl/kglparticlesitem.h>
using namespace std;

int main(int argc, char *argv[])
{
    KAboutData aboutData("kgl_tutorial2", 0,
                         ki18n("gluon"), "1.0",
                         ki18n("gluon"),
                         KAboutData::License_GPL,
                         ki18n("Copyright (c) 2009 Developer"));
    KCmdLineArgs::init(argc, argv, &aboutData);

    KApplication app;

    KGLEngine * engine = new KGLEngine;
    KGLView * view = new KGLView(engine);

    KGLParticlesItem * explose = new KGLParticlesItem;
    explose->createSmoke(40,KIcon("kgl").pixmap(32,32),45,0.07,0.003,32);
    engine->addItem(explose);
    explose->setPosition(-10,-10);
    explose->setAngle(0);
    explose->updateTransform();

    KGLParticlesItem * explose2 = new KGLParticlesItem;
    explose2->createSmoke(40,KIcon("kal").pixmap(32,32),45,0.07,0.003,32);
    engine->addItem(explose2);
    explose2->setAngle(180);
    explose2->setPosition(10,10);
    explose2->updateTransform();

    KGLParticlesItem * gluon = new KGLParticlesItem;
    gluon->createExplose(40,KIcon("gluon").pixmap(32,32),360,0.1,0.01,25);
    engine->addItem(gluon);

    view->start();
    view->show();
    app.exec();

}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkBoundingBox_hxx
#define itkBoundingBox_hxx
#include "itkBoundingBox.h"

namespace itk
{
/**
 * Print out the bounding box.
 */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Bounding Box: ( ";
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    os << m_Bounds[2 * i] << "," << m_Bounds[2 * i + 1] << " ";
    }
  os << " )" << std::endl;
}

/**
 * Access routine to set the points container.
 */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetPoints(const PointsContainer *points)
{
  itkDebugMacro("setting Points container to " << points);
  if ( m_PointsContainer != points )
    {
    m_PointsContainer = points;
    this->Modified();
    }
}

/** Access routine to get the points container. */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
const typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                            TPointsContainer >::PointsContainer *
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetPoints() const
{
  itkDebugMacro("returning Points container of " << m_PointsContainer);

  return m_PointsContainer.GetPointer();
}

/** Compute and get the corners of the bounding box */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
auto
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ComputeCorners() const -> std::array<PointType, NumberOfCorners>
{
  std::array<PointType, NumberOfCorners> result;

  PointType center = this->GetCenter();
  PointType radius;

  for ( unsigned int i = 0; i < VPointDimension; i++ )
    {
    radius[i] = m_Bounds[2 * i + 1] - center[i];
    }

  for ( unsigned int j = 0; j < NumberOfCorners; j++ )
    {
    PointType pnt;
    for ( unsigned int i = 0; i < VPointDimension; i++ )
      {
      pnt[i] = center[i] + std::pow( -1.0, ( (double)( j / ( int( std::pow(2.0, (double)i) ) ) ) ) )
               * radius[i];
      }

    result[j] = pnt;
    }

  return result;
}

#if !defined(ITK_LEGACY_REMOVE)
/** Compute and get the corners of the bounding box */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
const typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                            TPointsContainer >::PointsContainer *
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetCorners()
{
  m_CornersContainer->clear();
  m_CornersContainer->reserve(NumberOfCorners);

  for (const PointType& pnt: this->ComputeCorners())
    {
    // Push back is not defined so we insert at the end of the list
    m_CornersContainer->InsertElement(m_CornersContainer->Size(), pnt);
    }

  return m_CornersContainer.GetPointer();
}
#endif

/** */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::BoundingBox():m_PointsContainer(nullptr)
{
  m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
bool
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ComputeBoundingBox() const
{
  if ( !m_PointsContainer )
    {
    if ( this->GetMTime() > m_BoundsMTime )
      {
      m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
      m_BoundsMTime.Modified();
      }
    return false;
    }

  if ( this->GetMTime() > m_BoundsMTime )
    {
    //iterate over points determining min/max
    //start by initializing the values
    if ( m_PointsContainer->Size() < 1 )
      {
      m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
      m_BoundsMTime.Modified();
      return false;
      }

    PointsContainerConstIterator        ci = m_PointsContainer->Begin();
    Point< TCoordRep, VPointDimension > point = ci->Value();      //point value
    for ( unsigned int i = 0; i < PointDimension; i++ )
      {
      m_Bounds[2 * i] = point[i];
      m_Bounds[2 * i + 1] = point[i];
      }
    ++ci;

    //use a const iterator to grab the points and compute
    //the bounding box.
    while ( ci != m_PointsContainer->End() )
      {
      point = ci->Value();     //point value
      for ( unsigned int i = 0; i < PointDimension; i++ )
        {
        if ( point[i] < m_Bounds[2 * i] )
          {
          m_Bounds[2 * i] = point[i];
          }
        if ( point[i] > m_Bounds[2 * i + 1] )
          {
          m_Bounds[2 * i + 1] = point[i];
          }
        }
      ++ci;
      } //for all points in container

    m_BoundsMTime.Modified();
    }

  return true;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetCenter() const
{
  this->ComputeBoundingBox();

  PointType center;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    center[i] = ( m_Bounds[2 * i] + m_Bounds[2 * i + 1] ) / 2.0;
    }

  return center;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMinimum() const
{
  this->ComputeBoundingBox();

  PointType minimum;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    minimum[i] = m_Bounds[2 * i];
    }

  return minimum;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetMinimum(const PointType & point)
{
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    m_Bounds[2 * i] = point[i];
    }

  m_BoundsMTime.Modified();
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMaximum() const
{
  this->ComputeBoundingBox();

  PointType maximum;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    maximum[i] = m_Bounds[2 * i + 1];
    }

  return maximum;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetMaximum(const PointType & point)
{
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    m_Bounds[2 * i + 1] = point[i];
    }

  m_BoundsMTime.Modified();
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ConsiderPoint(const PointType & point)
{
  bool changed = false;

  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    if ( point[i] < m_Bounds[2 * i] )
      {
      m_Bounds[2 * i] = point[i];
      changed = true;
      }
    if ( point[i] > m_Bounds[2 * i + 1] )
      {
      m_Bounds[2 * i + 1] = point[i];
      changed = true;
      }
    }

  if ( changed )
    {
    m_BoundsMTime.Modified();
    }
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::AccumulateType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetDiagonalLength2() const
{
  typename NumericTraits< CoordRepType >::AccumulateType
  dist2 = NumericTraits< CoordRepType >::ZeroValue();

  if ( this->ComputeBoundingBox() )
    {
    for ( unsigned int i = 0; i < PointDimension; i++ )
      {
      dist2 += ( m_Bounds[2 * i] - m_Bounds[2 * i + 1] )
               * ( m_Bounds[2 * i] - m_Bounds[2 * i + 1] );
      }
    }

  return dist2;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
bool
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::IsInside(const PointType & point) const
{
  unsigned int j = 0;
  unsigned int i = 0;

  while ( i < PointDimension )
    {
    if ( point[i] < m_Bounds[j++] )
      {
      return false;
      }
    if ( point[i] > m_Bounds[j++] )
      {
      return false;
      }
    i++;
    }
  return true;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
ModifiedTimeType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMTime() const
{
  ModifiedTimeType latestTime = Object::GetMTime();

  if ( m_PointsContainer )
    {
    if ( latestTime < m_PointsContainer->GetMTime() )
      {
      latestTime = m_PointsContainer->GetMTime();
      }
    }
  return latestTime;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::Pointer
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::DeepCopy() const
{
  Pointer clone = Self::New();

  // Connect the same points container into the clone
  clone->SetPoints(this->m_PointsContainer);

#if !defined( ITK_LEGACY_REMOVE )
  // Copy the corners into the clone.
  clone->m_CornersContainer->clear();

  PointsContainerConstIterator itr = this->m_CornersContainer->Begin();
  PointsContainerConstIterator end = this->m_CornersContainer->End();

  clone->m_CornersContainer->Reserve( this->m_CornersContainer->Size() );
  PointsContainerIterator dest = clone->m_CornersContainer->Begin();

  while ( itr != end )
    {
    dest.Value() = itr.Value();
    ++itr;
    }
#endif

  // Copy the bounds into the clone
  for ( unsigned int i = 0; i < 2 * PointDimension; i++ )
    {
    clone->m_Bounds[i] = this->m_Bounds[i];
    }

  return clone;
}
} // end namespace itk

#endif
<commit_msg>ENH: Follow up commit to fix itkBoundingBox with LEGACY support<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkBoundingBox_hxx
#define itkBoundingBox_hxx
#include "itkBoundingBox.h"

namespace itk
{
/**
 * Print out the bounding box.
 */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Bounding Box: ( ";
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    os << m_Bounds[2 * i] << "," << m_Bounds[2 * i + 1] << " ";
    }
  os << " )" << std::endl;
}

/**
 * Access routine to set the points container.
 */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetPoints(const PointsContainer *points)
{
  itkDebugMacro("setting Points container to " << points);
  if ( m_PointsContainer != points )
    {
    m_PointsContainer = points;
    this->Modified();
    }
}

/** Access routine to get the points container. */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
const typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                            TPointsContainer >::PointsContainer *
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetPoints() const
{
  itkDebugMacro("returning Points container of " << m_PointsContainer);

  return m_PointsContainer.GetPointer();
}

/** Compute and get the corners of the bounding box */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
auto
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ComputeCorners() const -> std::array<PointType, NumberOfCorners>
{
  std::array<PointType, NumberOfCorners> result;

  PointType center = this->GetCenter();
  PointType radius;

  for ( unsigned int i = 0; i < VPointDimension; i++ )
    {
    radius[i] = m_Bounds[2 * i + 1] - center[i];
    }

  for ( unsigned int j = 0; j < NumberOfCorners; j++ )
    {
    PointType pnt;
    for ( unsigned int i = 0; i < VPointDimension; i++ )
      {
      pnt[i] = center[i] + std::pow( -1.0, ( (double)( j / ( int( std::pow(2.0, (double)i) ) ) ) ) )
               * radius[i];
      }

    result[j] = pnt;
    }

  return result;
}

#if !defined(ITK_LEGACY_REMOVE)
/** Compute and get the corners of the bounding box */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
const typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                            TPointsContainer >::PointsContainer *
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetCorners()
{
  m_CornersContainer->Initialize();
  m_CornersContainer->Reserve(NumberOfCorners);

  for (const PointType& pnt: this->ComputeCorners())
    {
    // Push back is not defined so we insert at the end of the list
    m_CornersContainer->InsertElement(m_CornersContainer->Size(), pnt);
    }

  return m_CornersContainer.GetPointer();
}
#endif

/** */
template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::BoundingBox():m_PointsContainer(nullptr)
{
  m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
bool
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ComputeBoundingBox() const
{
  if ( !m_PointsContainer )
    {
    if ( this->GetMTime() > m_BoundsMTime )
      {
      m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
      m_BoundsMTime.Modified();
      }
    return false;
    }

  if ( this->GetMTime() > m_BoundsMTime )
    {
    //iterate over points determining min/max
    //start by initializing the values
    if ( m_PointsContainer->Size() < 1 )
      {
      m_Bounds.Fill(NumericTraits< CoordRepType >::ZeroValue());
      m_BoundsMTime.Modified();
      return false;
      }

    PointsContainerConstIterator        ci = m_PointsContainer->Begin();
    Point< TCoordRep, VPointDimension > point = ci->Value();      //point value
    for ( unsigned int i = 0; i < PointDimension; i++ )
      {
      m_Bounds[2 * i] = point[i];
      m_Bounds[2 * i + 1] = point[i];
      }
    ++ci;

    //use a const iterator to grab the points and compute
    //the bounding box.
    while ( ci != m_PointsContainer->End() )
      {
      point = ci->Value();     //point value
      for ( unsigned int i = 0; i < PointDimension; i++ )
        {
        if ( point[i] < m_Bounds[2 * i] )
          {
          m_Bounds[2 * i] = point[i];
          }
        if ( point[i] > m_Bounds[2 * i + 1] )
          {
          m_Bounds[2 * i + 1] = point[i];
          }
        }
      ++ci;
      } //for all points in container

    m_BoundsMTime.Modified();
    }

  return true;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetCenter() const
{
  this->ComputeBoundingBox();

  PointType center;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    center[i] = ( m_Bounds[2 * i] + m_Bounds[2 * i + 1] ) / 2.0;
    }

  return center;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMinimum() const
{
  this->ComputeBoundingBox();

  PointType minimum;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    minimum[i] = m_Bounds[2 * i];
    }

  return minimum;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetMinimum(const PointType & point)
{
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    m_Bounds[2 * i] = point[i];
    }

  m_BoundsMTime.Modified();
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::PointType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMaximum() const
{
  this->ComputeBoundingBox();

  PointType maximum;
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    maximum[i] = m_Bounds[2 * i + 1];
    }

  return maximum;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::SetMaximum(const PointType & point)
{
  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    m_Bounds[2 * i + 1] = point[i];
    }

  m_BoundsMTime.Modified();
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
void
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::ConsiderPoint(const PointType & point)
{
  bool changed = false;

  for ( unsigned int i = 0; i < PointDimension; i++ )
    {
    if ( point[i] < m_Bounds[2 * i] )
      {
      m_Bounds[2 * i] = point[i];
      changed = true;
      }
    if ( point[i] > m_Bounds[2 * i + 1] )
      {
      m_Bounds[2 * i + 1] = point[i];
      changed = true;
      }
    }

  if ( changed )
    {
    m_BoundsMTime.Modified();
    }
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::AccumulateType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetDiagonalLength2() const
{
  typename NumericTraits< CoordRepType >::AccumulateType
  dist2 = NumericTraits< CoordRepType >::ZeroValue();

  if ( this->ComputeBoundingBox() )
    {
    for ( unsigned int i = 0; i < PointDimension; i++ )
      {
      dist2 += ( m_Bounds[2 * i] - m_Bounds[2 * i + 1] )
               * ( m_Bounds[2 * i] - m_Bounds[2 * i + 1] );
      }
    }

  return dist2;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
bool
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::IsInside(const PointType & point) const
{
  unsigned int j = 0;
  unsigned int i = 0;

  while ( i < PointDimension )
    {
    if ( point[i] < m_Bounds[j++] )
      {
      return false;
      }
    if ( point[i] > m_Bounds[j++] )
      {
      return false;
      }
    i++;
    }
  return true;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
ModifiedTimeType
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::GetMTime() const
{
  ModifiedTimeType latestTime = Object::GetMTime();

  if ( m_PointsContainer )
    {
    if ( latestTime < m_PointsContainer->GetMTime() )
      {
      latestTime = m_PointsContainer->GetMTime();
      }
    }
  return latestTime;
}

template< typename TPointIdentifier, int VPointDimension,
          typename TCoordRep, typename TPointsContainer >
typename BoundingBox< TPointIdentifier, VPointDimension, TCoordRep,
                      TPointsContainer >::Pointer
BoundingBox< TPointIdentifier, VPointDimension, TCoordRep, TPointsContainer >
::DeepCopy() const
{
  Pointer clone = Self::New();

  // Connect the same points container into the clone
  clone->SetPoints(this->m_PointsContainer);

#if !defined( ITK_LEGACY_REMOVE )
  // Copy the corners into the clone.
  clone->m_CornersContainer->clear();

  PointsContainerConstIterator itr = this->m_CornersContainer->Begin();
  PointsContainerConstIterator end = this->m_CornersContainer->End();

  clone->m_CornersContainer->Reserve( this->m_CornersContainer->Size() );
  PointsContainerIterator dest = clone->m_CornersContainer->Begin();

  while ( itr != end )
    {
    dest.Value() = itr.Value();
    ++itr;
    }
#endif

  // Copy the bounds into the clone
  for ( unsigned int i = 0; i < 2 * PointDimension; i++ )
    {
    clone->m_Bounds[i] = this->m_Bounds[i];
    }

  return clone;
}
} // end namespace itk

#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef __itkImageSource_hxx
#define __itkImageSource_hxx
#include "itkImageSource.h"

#include "itkOutputDataObjectIterator.h"

#include "vnl/vnl_math.h"

namespace itk
{
/**
 *
 */
template< class TOutputImage >
ImageSource< TOutputImage >
::ImageSource()
{
  // Create the output. We use static_cast<> here because we know the default
  // output must be of type TOutputImage
  typename TOutputImage::Pointer output =
    static_cast< TOutputImage * >( this->MakeOutput(0).GetPointer() );
  this->ProcessObject::SetNumberOfRequiredOutputs(1);
  this->ProcessObject::SetNthOutput( 0, output.GetPointer() );

  // Set the default behavior of an image source to NOT release its
  // output bulk data prior to GenerateData() in case that bulk data
  // can be reused (an thus avoid a costly deallocate/allocate cycle).
  this->ReleaseDataBeforeUpdateFlagOff();
}

/**
 *
 */
template< class TOutputImage >
ProcessObject::DataObjectPointer
ImageSource< TOutputImage >
::MakeOutput(ProcessObject::DataObjectPointerArraySizeType)
{
  return TOutputImage::New().GetPointer();
}

/**
 *
 */
template< class TOutputImage >
typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput()
{

  // we assume that the first output is of the templated type
  return itkDynamicCastInDebugMode< TOutputImage * >( this->GetPrimaryOutput() );
}

/**
 *
 */
template< class TOutputImage >
const typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput() const
{
  if ( this->GetNumberOfOutputs() < 1 )
    {
    return 0;
    }

  // we assume that the first output is of the templated type
  return itkDynamicCastInDebugMode< const TOutputImage * >
         ( this->ProcessObject::GetOutput(0) );
}

/**
 *
 */
template< class TOutputImage >
typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput(unsigned int idx)
{
  TOutputImage *out = dynamic_cast< TOutputImage * >
                      ( this->ProcessObject::GetOutput(idx) );

  if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL )
    {
    itkWarningMacro (<< "Unable to convert output number " << idx << " to type " <<  typeid( OutputImageType ).name () );
    }
  return out;
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftOutput(DataObject *graft)
{
  this->GraftNthOutput(0, graft);
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftOutput(const DataObjectIdentifierType & key, DataObject *graft)
{
  if ( !graft )
    {
    itkExceptionMacro(<< "Requested to graft output that is a NULL pointer");
    }

  // we use the process object method since all out output may not be
  // of the same type
  DataObject *output = this->ProcessObject::GetOutput(key);

  // Call GraftImage to copy meta-information, regions, and the pixel container
  output->Graft(graft);
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftNthOutput(unsigned int idx, DataObject *graft)
{
  if ( idx >= this->GetNumberOfIndexedOutputs() )
    {
    itkExceptionMacro(<< "Requested to graft output " << idx
                      << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " indexed Outputs.");
    }
  this->GraftOutput( this->MakeNameFromOutputIndex(idx), graft );
}

//----------------------------------------------------------------------------
template< class TOutputImage >
unsigned int
ImageSource< TOutputImage >
::SplitRequestedRegion(unsigned int i, unsigned int num, OutputImageRegionType & splitRegion)
{
  // Get the output pointer
  OutputImageType *outputPtr = this->GetOutput();

  const typename TOutputImage::SizeType & requestedRegionSize =
    outputPtr->GetRequestedRegion().GetSize();

  int splitAxis;
  typename TOutputImage::IndexType splitIndex;
  typename TOutputImage::SizeType splitSize;

  // Initialize the splitRegion to the output requested region
  splitRegion = outputPtr->GetRequestedRegion();
  splitIndex = splitRegion.GetIndex();
  splitSize = splitRegion.GetSize();

  // split on the outermost dimension available
  splitAxis = outputPtr->GetImageDimension() - 1;
  while ( requestedRegionSize[splitAxis] == 1 )
    {
    --splitAxis;
    if ( splitAxis < 0 )
      { // cannot split
      itkDebugMacro("  Cannot Split");
      return 1;
      }
    }

  // determine the actual number of pieces that will be generated
  typename TOutputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
  unsigned int valuesPerThread = Math::Ceil< unsigned int >(range / (double)num);
  unsigned int maxThreadIdUsed = Math::Ceil< unsigned int >(range / (double)valuesPerThread) - 1;

  // Split the region
  if ( i < maxThreadIdUsed )
    {
    splitIndex[splitAxis] += i * valuesPerThread;
    splitSize[splitAxis] = valuesPerThread;
    }
  if ( i == maxThreadIdUsed )
    {
    splitIndex[splitAxis] += i * valuesPerThread;
    // last thread needs to process the "rest" dimension being split
    splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;
    }

  // set the split region ivars
  splitRegion.SetIndex(splitIndex);
  splitRegion.SetSize(splitSize);

  itkDebugMacro("  Split Piece: " << splitRegion);

  return maxThreadIdUsed + 1;
}

//----------------------------------------------------------------------------
template< class TOutputImage >
void
ImageSource< TOutputImage >
::AllocateOutputs()
{
  typedef ImageBase< OutputImageDimension > ImageBaseType;
  typename ImageBaseType::Pointer outputPtr;

  // Allocate the output memory
  for ( OutputDataObjectIterator it(this); !it.IsAtEnd(); it++ )
    {
    // Check whether the output is an image of the appropriate
    // dimension (use ProcessObject's version of the GetInput()
    // method since it returns the input as a pointer to a
    // DataObject as opposed to the subclass version which
    // static_casts the input to an TInputImage).
    outputPtr = dynamic_cast< ImageBaseType * >( it.GetOutput() );

    if ( outputPtr )
      {
      outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
      outputPtr->Allocate();
      }
    }
}

//----------------------------------------------------------------------------
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GenerateData()
{
  // Call a method that can be overriden by a subclass to allocate
  // memory for the filter's outputs
  this->AllocateOutputs();

  // Call a method that can be overridden by a subclass to perform
  // some calculations prior to splitting the main computations into
  // separate threads
  this->BeforeThreadedGenerateData();

  // Set up the multithreaded processing
  ThreadStruct str;
  str.Filter = this;

  this->GetMultiThreader()->SetNumberOfThreads( this->GetNumberOfThreads() );
  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);

  // multithread the execution
  this->GetMultiThreader()->SingleMethodExecute();

  // Call a method that can be overridden by a subclass to perform
  // some calculations after all the threads have completed
  this->AfterThreadedGenerateData();
}

//----------------------------------------------------------------------------
// The execute method created by the subclass.
template< class TOutputImage >
void
ImageSource< TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType &,
                       ThreadIdType)
{
// The following code is equivalent to:
// itkExceptionMacro("subclass should override this method!!!");
// The ExceptionMacro is not used because gcc warns that a
// 'noreturn' function does return
  std::ostringstream message;

  message << "itk::ERROR: " << this->GetNameOfClass()
          << "(" << this << "): " << "Subclass should override this method!!!" << std::endl
          << "The signature of ThreadedGenerateData() has been changed in ITK v4 to use the new ThreadIdType." << std::endl
          << this->GetNameOfClass() << "::ThreadedGenerateData() might need to be updated to used it.";
  ExceptionObject e_(__FILE__, __LINE__, message.str().c_str(), ITK_LOCATION);
  throw e_;
}

// Callback routine used by the threading library. This routine just calls
// the ThreadedGenerateData method after setting the correct region for this
// thread.
template< class TOutputImage >
ITK_THREAD_RETURN_TYPE
ImageSource< TOutputImage >
::ThreaderCallback(void *arg)
{
  ThreadStruct *str;
  ThreadIdType  total, threadId, threadCount;

  threadId = ( (MultiThreader::ThreadInfoStruct *)( arg ) )->ThreadID;
  threadCount = ( (MultiThreader::ThreadInfoStruct *)( arg ) )->NumberOfThreads;

  str = (ThreadStruct *)( ( (MultiThreader::ThreadInfoStruct *)( arg ) )->UserData );

  // execute the actual method with appropriate output region
  // first find out how many pieces extent can be split into.
  typename TOutputImage::RegionType splitRegion;
  total = str->Filter->SplitRequestedRegion(threadId, threadCount,
                                            splitRegion);

  if ( threadId < total )
    {
    str->Filter->ThreadedGenerateData(splitRegion, threadId);
    }
  // else
  //   {
  //   otherwise don't use this thread. Sometimes the threads dont
  //   break up very well and it is just as efficient to leave a
  //   few threads idle.
  //   }

  return ITK_THREAD_RETURN_VALUE;
}
} // end namespace itk

#endif
<commit_msg>PERF: Use GetPrimaryOutput in ImageSource GetOutput.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef __itkImageSource_hxx
#define __itkImageSource_hxx
#include "itkImageSource.h"

#include "itkOutputDataObjectIterator.h"

#include "vnl/vnl_math.h"

namespace itk
{
/**
 *
 */
template< class TOutputImage >
ImageSource< TOutputImage >
::ImageSource()
{
  // Create the output. We use static_cast<> here because we know the default
  // output must be of type TOutputImage
  typename TOutputImage::Pointer output =
    static_cast< TOutputImage * >( this->MakeOutput(0).GetPointer() );
  this->ProcessObject::SetNumberOfRequiredOutputs(1);
  this->ProcessObject::SetNthOutput( 0, output.GetPointer() );

  // Set the default behavior of an image source to NOT release its
  // output bulk data prior to GenerateData() in case that bulk data
  // can be reused (an thus avoid a costly deallocate/allocate cycle).
  this->ReleaseDataBeforeUpdateFlagOff();
}

/**
 *
 */
template< class TOutputImage >
ProcessObject::DataObjectPointer
ImageSource< TOutputImage >
::MakeOutput(ProcessObject::DataObjectPointerArraySizeType)
{
  return TOutputImage::New().GetPointer();
}

/**
 *
 */
template< class TOutputImage >
typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput()
{

  // we assume that the first output is of the templated type
  return itkDynamicCastInDebugMode< TOutputImage * >( this->GetPrimaryOutput() );
}

/**
 *
 */
template< class TOutputImage >
const typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput() const
{
  // we assume that the first output is of the templated type
  return itkDynamicCastInDebugMode< const TOutputImage * >( this->GetPrimaryOutput() );
}

/**
 *
 */
template< class TOutputImage >
typename ImageSource< TOutputImage >::OutputImageType *
ImageSource< TOutputImage >
::GetOutput(unsigned int idx)
{
  TOutputImage *out = dynamic_cast< TOutputImage * >
                      ( this->ProcessObject::GetOutput(idx) );

  if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL )
    {
    itkWarningMacro (<< "Unable to convert output number " << idx << " to type " <<  typeid( OutputImageType ).name () );
    }
  return out;
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftOutput(DataObject *graft)
{
  this->GraftNthOutput(0, graft);
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftOutput(const DataObjectIdentifierType & key, DataObject *graft)
{
  if ( !graft )
    {
    itkExceptionMacro(<< "Requested to graft output that is a NULL pointer");
    }

  // we use the process object method since all out output may not be
  // of the same type
  DataObject *output = this->ProcessObject::GetOutput(key);

  // Call GraftImage to copy meta-information, regions, and the pixel container
  output->Graft(graft);
}

/**
 *
 */
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GraftNthOutput(unsigned int idx, DataObject *graft)
{
  if ( idx >= this->GetNumberOfIndexedOutputs() )
    {
    itkExceptionMacro(<< "Requested to graft output " << idx
                      << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " indexed Outputs.");
    }
  this->GraftOutput( this->MakeNameFromOutputIndex(idx), graft );
}

//----------------------------------------------------------------------------
template< class TOutputImage >
unsigned int
ImageSource< TOutputImage >
::SplitRequestedRegion(unsigned int i, unsigned int num, OutputImageRegionType & splitRegion)
{
  // Get the output pointer
  OutputImageType *outputPtr = this->GetOutput();

  const typename TOutputImage::SizeType & requestedRegionSize =
    outputPtr->GetRequestedRegion().GetSize();

  int splitAxis;
  typename TOutputImage::IndexType splitIndex;
  typename TOutputImage::SizeType splitSize;

  // Initialize the splitRegion to the output requested region
  splitRegion = outputPtr->GetRequestedRegion();
  splitIndex = splitRegion.GetIndex();
  splitSize = splitRegion.GetSize();

  // split on the outermost dimension available
  splitAxis = outputPtr->GetImageDimension() - 1;
  while ( requestedRegionSize[splitAxis] == 1 )
    {
    --splitAxis;
    if ( splitAxis < 0 )
      { // cannot split
      itkDebugMacro("  Cannot Split");
      return 1;
      }
    }

  // determine the actual number of pieces that will be generated
  typename TOutputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
  unsigned int valuesPerThread = Math::Ceil< unsigned int >(range / (double)num);
  unsigned int maxThreadIdUsed = Math::Ceil< unsigned int >(range / (double)valuesPerThread) - 1;

  // Split the region
  if ( i < maxThreadIdUsed )
    {
    splitIndex[splitAxis] += i * valuesPerThread;
    splitSize[splitAxis] = valuesPerThread;
    }
  if ( i == maxThreadIdUsed )
    {
    splitIndex[splitAxis] += i * valuesPerThread;
    // last thread needs to process the "rest" dimension being split
    splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;
    }

  // set the split region ivars
  splitRegion.SetIndex(splitIndex);
  splitRegion.SetSize(splitSize);

  itkDebugMacro("  Split Piece: " << splitRegion);

  return maxThreadIdUsed + 1;
}

//----------------------------------------------------------------------------
template< class TOutputImage >
void
ImageSource< TOutputImage >
::AllocateOutputs()
{
  typedef ImageBase< OutputImageDimension > ImageBaseType;
  typename ImageBaseType::Pointer outputPtr;

  // Allocate the output memory
  for ( OutputDataObjectIterator it(this); !it.IsAtEnd(); it++ )
    {
    // Check whether the output is an image of the appropriate
    // dimension (use ProcessObject's version of the GetInput()
    // method since it returns the input as a pointer to a
    // DataObject as opposed to the subclass version which
    // static_casts the input to an TInputImage).
    outputPtr = dynamic_cast< ImageBaseType * >( it.GetOutput() );

    if ( outputPtr )
      {
      outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
      outputPtr->Allocate();
      }
    }
}

//----------------------------------------------------------------------------
template< class TOutputImage >
void
ImageSource< TOutputImage >
::GenerateData()
{
  // Call a method that can be overriden by a subclass to allocate
  // memory for the filter's outputs
  this->AllocateOutputs();

  // Call a method that can be overridden by a subclass to perform
  // some calculations prior to splitting the main computations into
  // separate threads
  this->BeforeThreadedGenerateData();

  // Set up the multithreaded processing
  ThreadStruct str;
  str.Filter = this;

  this->GetMultiThreader()->SetNumberOfThreads( this->GetNumberOfThreads() );
  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);

  // multithread the execution
  this->GetMultiThreader()->SingleMethodExecute();

  // Call a method that can be overridden by a subclass to perform
  // some calculations after all the threads have completed
  this->AfterThreadedGenerateData();
}

//----------------------------------------------------------------------------
// The execute method created by the subclass.
template< class TOutputImage >
void
ImageSource< TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType &,
                       ThreadIdType)
{
// The following code is equivalent to:
// itkExceptionMacro("subclass should override this method!!!");
// The ExceptionMacro is not used because gcc warns that a
// 'noreturn' function does return
  std::ostringstream message;

  message << "itk::ERROR: " << this->GetNameOfClass()
          << "(" << this << "): " << "Subclass should override this method!!!" << std::endl
          << "The signature of ThreadedGenerateData() has been changed in ITK v4 to use the new ThreadIdType." << std::endl
          << this->GetNameOfClass() << "::ThreadedGenerateData() might need to be updated to used it.";
  ExceptionObject e_(__FILE__, __LINE__, message.str().c_str(), ITK_LOCATION);
  throw e_;
}

// Callback routine used by the threading library. This routine just calls
// the ThreadedGenerateData method after setting the correct region for this
// thread.
template< class TOutputImage >
ITK_THREAD_RETURN_TYPE
ImageSource< TOutputImage >
::ThreaderCallback(void *arg)
{
  ThreadStruct *str;
  ThreadIdType  total, threadId, threadCount;

  threadId = ( (MultiThreader::ThreadInfoStruct *)( arg ) )->ThreadID;
  threadCount = ( (MultiThreader::ThreadInfoStruct *)( arg ) )->NumberOfThreads;

  str = (ThreadStruct *)( ( (MultiThreader::ThreadInfoStruct *)( arg ) )->UserData );

  // execute the actual method with appropriate output region
  // first find out how many pieces extent can be split into.
  typename TOutputImage::RegionType splitRegion;
  total = str->Filter->SplitRequestedRegion(threadId, threadCount,
                                            splitRegion);

  if ( threadId < total )
    {
    str->Filter->ThreadedGenerateData(splitRegion, threadId);
    }
  // else
  //   {
  //   otherwise don't use this thread. Sometimes the threads dont
  //   break up very well and it is just as efficient to leave a
  //   few threads idle.
  //   }

  return ITK_THREAD_RETURN_VALUE;
}
} // end namespace itk

#endif
<|endoftext|>