blob: 91d29840722b02504de2c5d73b30748e53317d65 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 "TimeUnit.h"
#include <decaf/lang/Long.h>
#include <decaf/lang/Thread.h>
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::util;
using namespace decaf::util::concurrent;
////////////////////////////////////////////////////////////////////////////////
const TimeUnit TimeUnit::NANOSECONDS( 0, "NANOSECONDS" );
const TimeUnit TimeUnit::MICROSECONDS( 1, "MICROSECONDS" );
const TimeUnit TimeUnit::MILLISECONDS( 2, "MILLISECONDS" );
const TimeUnit TimeUnit::SECONDS( 3, "SECONDS" );
const TimeUnit TimeUnit::MINUTES( 4, "MINUTES" );
const TimeUnit TimeUnit::HOURS( 5, "HOURS" );
const TimeUnit TimeUnit::DAYS( 6, "DAYS" );
////////////////////////////////////////////////////////////////////////////////
const TimeUnit* const TimeUnit::values[] = {
&NANOSECONDS,
&MICROSECONDS,
&MILLISECONDS,
&SECONDS,
&MINUTES,
&HOURS,
&DAYS
};
////////////////////////////////////////////////////////////////////////////////
const long long TimeUnit::multipliers[] = {
1,
1000LL,
1000LL * 1000LL,
1000LL * 1000LL * 1000LL,
1000LL * 1000LL * 1000LL * 60LL,
1000LL * 1000LL * 1000LL * 60LL * 60LL,
1000LL * 1000LL * 1000LL * 60LL * 60LL * 24LL,
};
////////////////////////////////////////////////////////////////////////////////
TimeUnit::TimeUnit( int index, const std::string& name ) : index(index), name(name) {
}
////////////////////////////////////////////////////////////////////////////////
long long TimeUnit::convert( long long sourceDuration, const TimeUnit& sourceUnit ) const {
return this->doConvert( sourceUnit.index, this->index, sourceDuration );
}
////////////////////////////////////////////////////////////////////////////////
long long TimeUnit::doConvert( int srcIndex, int destIndex, long long duration ) const {
if( duration == 0 ) {
return duration;
} else if( srcIndex > destIndex ) {
return scale( duration,
multipliers[srcIndex] / multipliers[destIndex],
Long::MAX_VALUE / ( multipliers[srcIndex] / multipliers[destIndex] ) );
} else if( srcIndex < destIndex ) {
return duration / ( multipliers[destIndex] / multipliers[srcIndex] );
}
// Same unit, no conversion.
return duration;
}
////////////////////////////////////////////////////////////////////////////////
int TimeUnit::excessNanos( long long time, long long ms ) const {
if( *this == NANOSECONDS ) {
return (int)( time - ( ms * 1000 * 1000 ) );
} else if( *this == MICROSECONDS ) {
return (int)( ( time * 1000 ) - ( ms * 1000 * 1000 ) );
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
void TimeUnit::sleep( long long timeout ) const {
if( timeout > 0 ) {
long long ms = toMillis( timeout );
int ns = excessNanos( timeout, ms );
Thread::sleep( ms, ns );
}
}
////////////////////////////////////////////////////////////////////////////////
void TimeUnit::timedWait( Synchronizable* obj, long long timeout ) const {
if( obj == NULL ) {
throw NullPointerException(
__FILE__, __LINE__, "Synchronizable object pointer was null." );
}
if( timeout > 0 ) {
long long ms = toMillis( timeout );
int ns = excessNanos( timeout, ms );
obj->wait( ms, ns );
}
}
////////////////////////////////////////////////////////////////////////////////
void TimeUnit::timedJoin( Thread* thread, long long timeout ) {
if( thread == NULL ) {
throw NullPointerException(
__FILE__, __LINE__, "Thread object pointer was null." );
}
if( timeout > 0 ) {
long long ms = toMillis( timeout );
int ns = excessNanos( timeout, ms );
thread->join( ms, ns );
}
}
////////////////////////////////////////////////////////////////////////////////
std::string TimeUnit::toString() const {
return this->name;
}
////////////////////////////////////////////////////////////////////////////////
int TimeUnit::compareTo( const TimeUnit& value ) const {
return index == value.index ? 0 : ( index > value.index ? 1 : -1 );
}
////////////////////////////////////////////////////////////////////////////////
bool TimeUnit::equals( const TimeUnit& value ) const {
return index == value.index;
}
////////////////////////////////////////////////////////////////////////////////
bool TimeUnit::operator==( const TimeUnit& value ) const {
return index == value.index;
}
////////////////////////////////////////////////////////////////////////////////
bool TimeUnit::operator<( const TimeUnit& value ) const {
return this->compareTo( value ) == -1;
}
////////////////////////////////////////////////////////////////////////////////
long long TimeUnit::scale( long long duration, long long multiplier, long long overflow ) {
if( duration > overflow ) {
return Long::MAX_VALUE;
} else if( duration < -overflow ) {
return Long::MIN_VALUE;
}
return duration * multiplier;
}
////////////////////////////////////////////////////////////////////////////////
const TimeUnit& TimeUnit::valueOf( const std::string& name ) {
for( int i = 0; i < 7; ++i ) {
if( values[i]->name == name ) {
return *values[i];
}
}
throw IllegalArgumentException(
__FILE__, __LINE__,
"Passed TimeUnit name; %s, Does not match any instances of TimeUnit",
name.c_str() );
}