/* -*- c++ -*- */
/*
* Copyright 2004,2007,2009,2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/ #ifndef INCLUDED_GR_RUNTIME_BLOCK_H
#define INCLUDED_GR_RUNTIME_BLOCK_H #include <gnuradio/api.h>
#include <gnuradio/basic_block.h>
#include <gnuradio/tags.h>
#include <gnuradio/logger.h> namespace gr { /*!
* \brief The abstract base class for all 'terminal' processing blocks.
* \ingroup base_blk
*
* A signal processing flow is constructed by creating a tree of
* hierarchical blocks, which at any level may also contain terminal
* nodes that actually implement signal processing functions. This
* is the base class for all such leaf nodes.
*
* Blocks have a set of input streams and output streams. The
* input_signature and output_signature define the number of input
* streams and output streams respectively, and the type of the data
* items in each stream.
*
* Although blocks may consume data on each input stream at a
* different rate, all outputs streams must produce data at the same
* rate. That rate may be different from any of the input rates.
*
* User derived blocks override two methods, forecast and
* general_work, to implement their signal processing
* behavior. forecast is called by the system scheduler to determine
* how many items are required on each input stream in order to
* produce a given number of output items.
*
* general_work is called to perform the signal processing in the
* block. It reads the input items and writes the output items.
*/
class GR_RUNTIME_API block : public basic_block
{
public: //! Magic return values from general_work
enum {
WORK_CALLED_PRODUCE = -2,
WORK_DONE = -1
}; enum tag_propagation_policy_t {
TPP_DONT = 0,
TPP_ALL_TO_ALL = 1,
TPP_ONE_TO_ONE = 2
}; virtual ~block(); /*!
* Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...)
* History is the number of x_i's that are examined to produce one y_i.
* This comes in handy for FIR filters, where we use history to
* ensure that our input contains the appropriate "history" for the
* filter. History should be equal to the number of filter taps.
*/
unsigned history() const;
void set_history(unsigned history); /*!
* Declares the block's delay in samples. Since the delay of
* blocks like filters is derived from the taps and not the block
* itself, we cannot automatically calculate this value and so
* leave it as a user-defined property. It defaults to 0 is not
* set.
*
* This does not actively set the delay; it just tells the
* scheduler what the delay is.
*
* This delay is mostly used to adjust the placement of the tags
* and is not currently used for any signal processing. When a tag
* is passed through a block with internal delay, its location
* should be moved based on the delay of the block. This interface
* allows us to tell the scheduler this value.
*
* \param which The buffer on which to set the delay.
* \param delay The sample delay of the data stream.
*/
void declare_sample_delay(int which, unsigned delay); /*!
* Convenience wrapper to gr::block::declare_delay(int which, unsigned delay)
* to set all ports to the same delay.
*/
void declare_sample_delay(unsigned delay); /*!
* Gets the delay of the block. Since the delay of blocks like
* filters is derived from the taps and not the block itself, we
* cannot automatically calculate this value and so leave it as a
* user-defined property. It defaults to 0 is not set.
*
* \param which Which port from which to get the sample delay.
*/
unsigned sample_delay(int which) const; /*!
* \brief Return true if this block has a fixed input to output rate.
*
* If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
*/
bool fixed_rate() const { return d_fixed_rate; } // ----------------------------------------------------------------
// override these to define your behavior
// ---------------------------------------------------------------- /*!
* \brief Estimate input requirements given output request
*
* \param noutput_items number of output items to produce
* \param ninput_items_required number of input items required on each input stream
*
* Given a request to product \p noutput_items, estimate the
* number of data items required on each input stream. The
* estimate doesn't have to be exact, but should be close.
*/
virtual void forecast(int noutput_items,
gr_vector_int &ninput_items_required); /*!
* \brief compute output items from input items
*
* \param noutput_items number of output items to write on each output stream
* \param ninput_items number of input items available on each input stream
* \param input_items vector of pointers to the input items, one entry per input stream
* \param output_items vector of pointers to the output items, one entry per output stream
*
* \returns number of items actually written to each output stream, or -1 on EOF.
* It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items
*
* general_work must call consume or consume_each to indicate how
* many items were consumed on each input stream.
*/
virtual int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items); /*!
* \brief Called to enable drivers, etc for i/o devices.
*
* This allows a block to enable an associated driver to begin
* transfering data just before we start to execute the scheduler.
* The end result is that this reduces latency in the pipeline
* when dealing with audio devices, usrps, etc.
*/
virtual bool start(); /*!
* \brief Called to disable drivers, etc for i/o devices.
*/
virtual bool stop(); // ---------------------------------------------------------------- /*!
* \brief Constrain the noutput_items argument passed to forecast and general_work
*
* set_output_multiple causes the scheduler to ensure that the
* noutput_items argument passed to forecast and general_work will
* be an integer multiple of \param multiple The default value of
* output multiple is 1.
*/
void set_output_multiple(int multiple);
int output_multiple() const { return d_output_multiple; }
bool output_multiple_set() const { return d_output_multiple_set; } /*!
* \brief Constrains buffers to work on a set item alignment (for SIMD)
*
* set_alignment_multiple causes the scheduler to ensure that the
* noutput_items argument passed to forecast and general_work will
* be an integer multiple of \param multiple The default value is
* 1.
*
* This control is similar to the output_multiple setting, except
* that if the number of items passed to the block is less than
* the output_multiple, this value is ignored and the block can
* produce like normal. The d_unaligned value is set to the number
* of items the block is off by. In the next call to general_work,
* the noutput_items is set to d_unaligned or less until
* d_unaligned==0. The buffers are now aligned again and the
* aligned calls can be performed again.
*/
void set_alignment(int multiple);
int alignment() const { return d_output_multiple; } void set_unaligned(int na);
int unaligned() const { return d_unaligned; }
void set_is_unaligned(bool u);
bool is_unaligned() const { return d_is_unaligned; } /*!
* \brief Tell the scheduler \p how_many_items of input stream \p
* which_input were consumed.
* This function should be called at the end of work() or general_work(), after all processing is finished.
*/
void consume(int which_input, int how_many_items); /*!
* \brief Tell the scheduler \p how_many_items were consumed on
* each input stream.
*/
void consume_each(int how_many_items); /*!
* \brief Tell the scheduler \p how_many_items were produced on
* output stream \p which_output.
*
* If the block's general_work method calls produce, \p
* general_work must return WORK_CALLED_PRODUCE.
*/
void produce(int which_output, int how_many_items); /*!
* \brief Set the approximate output rate / input rate
*
* Provide a hint to the buffer allocator and scheduler.
* The default relative_rate is 1.0
*
* decimators have relative_rates < 1.0
* interpolators have relative_rates > 1.0
*/
void set_relative_rate(double relative_rate); /*!
* \brief return the approximate output rate / input rate
*/
double relative_rate() const { return d_relative_rate; } /*
* The following two methods provide special case info to the
* scheduler in the event that a block has a fixed input to output
* ratio. sync_block, sync_decimator and
* sync_interpolator override these. If you're fixed rate,
* subclass one of those.
*/
/*!
* \brief Given ninput samples, return number of output samples that will be produced.
* N.B. this is only defined if fixed_rate returns true.
* Generally speaking, you don't need to override this.
*/
virtual int fixed_rate_ninput_to_noutput(int ninput); /*!
* \brief Given noutput samples, return number of input samples required to produce noutput.
* N.B. this is only defined if fixed_rate returns true.
* Generally speaking, you don't need to override this.
*/
virtual int fixed_rate_noutput_to_ninput(int noutput); /*!
* \brief Return the number of items read on input stream which_input
*/
uint64_t nitems_read(unsigned int which_input); /*!
* \brief Return the number of items written on output stream which_output
*/
uint64_t nitems_written(unsigned int which_output); /*!
* \brief Asks for the policy used by the scheduler to moved tags downstream.
*/
tag_propagation_policy_t tag_propagation_policy(); /*!
* \brief Set the policy by the scheduler to determine how tags are moved downstream.
*/
void set_tag_propagation_policy(tag_propagation_policy_t p); /*!
* \brief Return the minimum number of output items this block can
* produce during a call to work.
*
* Should be 0 for most blocks. Useful if we're dealing with
* packets and the block produces one packet per call to work.
*/
int min_noutput_items() const { return d_min_noutput_items; } /*!
* \brief Set the minimum number of output items this block can
* produce during a call to work.
*
* \param m the minimum noutput_items this block can produce.
*/
void set_min_noutput_items(int m) { d_min_noutput_items = m; } /*!
* \brief Return the maximum number of output items this block will
* handle during a call to work.
*/
int max_noutput_items(); /*!
* \brief Set the maximum number of output items this block will
* handle during a call to work.
*
* \param m the maximum noutput_items this block will handle.
*/
void set_max_noutput_items(int m); /*!
* \brief Clear the switch for using the max_noutput_items value of this block.
*
* When is_set_max_noutput_items() returns 'true', the scheduler
* will use the value returned by max_noutput_items() to limit the
* size of the number of items possible for this block's work
* function. If is_set_max_notput_items() returns 'false', then
* the scheduler ignores the internal value and uses the value set
* globally in the top_block.
*
* Use this value to clear the 'is_set' flag so the scheduler will
* ignore this. Use the set_max_noutput_items(m) call to both set
* a new value for max_noutput_items and to reenable its use in
* the scheduler.
*/
void unset_max_noutput_items(); /*!
* \brief Ask the block if the flag is or is not set to use the
* internal value of max_noutput_items during a call to work.
*/
bool is_set_max_noutput_items(); /*
* Used to expand the vectors that hold the min/max buffer sizes.
*
* Specifically, when -1 is used, the vectors are just initialized
* with 1 value; this is used by the flat_flowgraph to expand when
* required to add a new value for new ports on these blocks.
*/
void expand_minmax_buffer(int port); /*!
* \brief Returns max buffer size on output port \p i.
*/
long max_output_buffer(size_t i); /*!
* \brief Request limit on max buffer size on all output ports.
*
* \details
* This is an advanced feature. Calling this can affect some
* fundamental assumptions about the system behavior and
* performance.
*
* The actual buffer size is determined by a number of other
* factors from the block and system. This function only provides
* a requested maximum. The buffers will always be a multiple of
* the system page size, which may be larger than the value asked
* for here.
*
* \param max_output_buffer the requested maximum output size in items.
*/
void set_max_output_buffer(long max_output_buffer); /*!
* \brief Request limit on max buffer size on output port \p port.
*
* \details
* This is an advanced feature. Calling this can affect some
* fundamental assumptions about the system behavior and
* performance.
*
* The actual buffer size is determined by a number of other
* factors from the block and system. This function only provides
* a requested maximum. The buffers will always be a multiple of
* the system page size, which may be larger than the value asked
* for here.
*
* \param port the output port the request applies to.
* \param max_output_buffer the requested maximum output size in items.
*/
void set_max_output_buffer(int port, long max_output_buffer); /*!
* \brief Returns min buffer size on output port \p i.
*/
long min_output_buffer(size_t i); /*!
* \brief Request limit on the mininum buffer size on all output
* ports.
*
* \details
* This is an advanced feature. Calling this can affect some
* fundamental assumptions about the system behavior and
* performance.
*
* The actual buffer size is determined by a number of other
* factors from the block and system. This function only provides
* a requested minimum. The buffers will always be a multiple of
* the system page size, which may be larger than the value asked
* for here.
*
* \param min_output_buffer the requested minimum output size in items.
*/
void set_min_output_buffer(long min_output_buffer); /*!
* \brief Request limit on min buffer size on output port \p port.
*
* \details
* This is an advanced feature. Calling this can affect some
* fundamental assumptions about the system behavior and
* performance.
*
* The actual buffer size is determined by a number of other
* factors from the block and system. This function only provides
* a requested minimum. The buffers will always be a multiple of
* the system page size, which may be larger than the value asked
* for here.
*
* \param port the output port the request applies to.
* \param min_output_buffer the requested minimum output size in items.
*/
void set_min_output_buffer(int port, long min_output_buffer); // --------------- Performance counter functions ------------- /*!
* \brief Gets instantaneous noutput_items performance counter.
*/
float pc_noutput_items(); /*!
* \brief Gets average noutput_items performance counter.
*/
float pc_noutput_items_avg(); /*!
* \brief Gets variance of noutput_items performance counter.
*/
float pc_noutput_items_var(); /*!
* \brief Gets instantaneous num items produced performance counter.
*/
float pc_nproduced(); /*!
* \brief Gets average num items produced performance counter.
*/
float pc_nproduced_avg(); /*!
* \brief Gets variance of num items produced performance counter.
*/
float pc_nproduced_var(); /*!
* \brief Gets instantaneous fullness of \p which input buffer.
*/
float pc_input_buffers_full(int which); /*!
* \brief Gets average fullness of \p which input buffer.
*/
float pc_input_buffers_full_avg(int which); /*!
* \brief Gets variance of fullness of \p which input buffer.
*/
float pc_input_buffers_full_var(int which); /*!
* \brief Gets instantaneous fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full(); /*!
* \brief Gets average fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full_avg(); /*!
* \brief Gets variance of fullness of all input buffers.
*/
std::vector<float> pc_input_buffers_full_var(); /*!
* \brief Gets instantaneous fullness of \p which input buffer.
*/
float pc_output_buffers_full(int which); /*!
* \brief Gets average fullness of \p which input buffer.
*/
float pc_output_buffers_full_avg(int which); /*!
* \brief Gets variance of fullness of \p which input buffer.
*/
float pc_output_buffers_full_var(int which); /*!
* \brief Gets instantaneous fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full(); /*!
* \brief Gets average fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full_avg(); /*!
* \brief Gets variance of fullness of all output buffers.
*/
std::vector<float> pc_output_buffers_full_var(); /*!
* \brief Gets instantaneous clock cycles spent in work.
*/
float pc_work_time(); /*!
* \brief Gets average clock cycles spent in work.
*/
float pc_work_time_avg(); /*!
* \brief Gets average clock cycles spent in work.
*/
float pc_work_time_var(); /*!
* \brief Gets total clock cycles spent in work.
*/
float pc_work_time_total(); /*!
* \brief Gets average throughput.
*/
float pc_throughput_avg(); /*!
* \brief Resets the performance counters
*/
void reset_perf_counters(); /*!
* \brief Sets up export of perf. counters to ControlPort. Only
* called by the scheduler.
*/
void setup_pc_rpc(); /*!
* \brief Checks if this block is already exporting perf. counters
* to ControlPort.
*/
bool is_pc_rpc_set() { return d_pc_rpc_set; } /*!
* \brief If the block calls this in its constructor, it's
* perf. counters will not be exported.
*/
void no_pc_rpc() { d_pc_rpc_set = true; } // ----------------------------------------------------------------------------
// Functions to handle thread affinity /*!
* \brief Set the thread's affinity to processor core \p n.
*
* \param mask a vector of ints of the core numbers available to this block.
*/
void set_processor_affinity(const std::vector<int> &mask); /*!
* \brief Remove processor affinity to a specific core.
*/
void unset_processor_affinity(); /*!
* \brief Get the current processor affinity.
*/
std::vector<int> processor_affinity() { return d_affinity; } /*!
* \brief Get the current thread priority in use
*/
int active_thread_priority(); /*!
* \brief Get the current thread priority stored
*/
int thread_priority(); /*!
* \brief Set the current thread priority
*/
int set_thread_priority(int priority); bool update_rate() const; // ---------------------------------------------------------------------------- /*!
* \brief the system message handler
*/
void system_handler(pmt::pmt_t msg); /*!
* \brief returns true when execution has completed due to a message connection
*/
bool finished(); private:
int d_output_multiple;
bool d_output_multiple_set;
int d_unaligned;
bool d_is_unaligned;
double d_relative_rate; // approx output_rate / input_rate
block_detail_sptr d_detail; // implementation details
unsigned d_history;
unsigned d_attr_delay; // the block's sample delay
bool d_fixed_rate;
bool d_max_noutput_items_set; // if d_max_noutput_items is valid
int d_max_noutput_items; // value of max_noutput_items for this block
int d_min_noutput_items;
tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
std::vector<int> d_affinity; // thread affinity proc. mask
int d_priority; // thread priority level
bool d_pc_rpc_set;
bool d_update_rate; // should sched update rel rate?
bool d_finished; // true if msg ports think we are finished protected:
block(void) {} // allows pure virtual interface sub-classes
block(const std::string &name,
gr::io_signature::sptr input_signature,
gr::io_signature::sptr output_signature); void set_fixed_rate(bool fixed_rate) { d_fixed_rate = fixed_rate; } /*!
* \brief Adds a new tag onto the given output buffer.
*
* \param which_output an integer of which output stream to attach the tag
* \param abs_offset a uint64 number of the absolute item number
* assicated with the tag. Can get from nitems_written.
* \param key the tag key as a PMT symbol
* \param value any PMT holding any value for the given key
* \param srcid optional source ID specifier; defaults to PMT_F
*/
inline void add_item_tag(unsigned int which_output,
uint64_t abs_offset,
const pmt::pmt_t &key,
const pmt::pmt_t &value,
const pmt::pmt_t &srcid=pmt::PMT_F)
{
tag_t tag;
tag.offset = abs_offset;
tag.key = key;
tag.value = value;
tag.srcid = srcid;
this->add_item_tag(which_output, tag);
} /*!
* \brief Adds a new tag onto the given output buffer.
*
* \param which_output an integer of which output stream to attach the tag
* \param tag the tag object to add
*/
void add_item_tag(unsigned int which_output, const tag_t &tag); /*!
* \brief DEPRECATED. Will be removed in 3.8.
*
* \param which_input an integer of which input stream to remove the tag from
* \param abs_offset a uint64 number of the absolute item number
* assicated with the tag. Can get from nitems_written.
* \param key the tag key as a PMT symbol
* \param value any PMT holding any value for the given key
* \param srcid optional source ID specifier; defaults to PMT_F
*
* If no such tag is found, does nothing.
*/
inline void remove_item_tag(unsigned int which_input,
uint64_t abs_offset,
const pmt::pmt_t &key,
const pmt::pmt_t &value,
const pmt::pmt_t &srcid=pmt::PMT_F)
{
tag_t tag;
tag.offset = abs_offset;
tag.key = key;
tag.value = value;
tag.srcid = srcid;
this->remove_item_tag(which_input, tag);
} /*!
* \brief DEPRECATED. Will be removed in 3.8.
*
* \param which_input an integer of which input stream to remove the tag from
* \param tag the tag object to remove
*/
void remove_item_tag(unsigned int which_input, const tag_t &tag); /*!
* \brief Given a [start,end), returns a vector of all tags in the range.
*
* Range of counts is from start to end-1.
*
* Tags are tuples of:
* (item count, source id, key, value)
*
* \param v a vector reference to return tags into
* \param which_input an integer of which input stream to pull from
* \param abs_start a uint64 count of the start of the range of interest
* \param abs_end a uint64 count of the end of the range of interest
*/
void get_tags_in_range(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end); /*!
* \brief Given a [start,end), returns a vector of all tags in the
* range with a given key.
*
* Range of counts is from start to end-1.
*
* Tags are tuples of:
* (item count, source id, key, value)
*
* \param v a vector reference to return tags into
* \param which_input an integer of which input stream to pull from
* \param abs_start a uint64 count of the start of the range of interest
* \param abs_end a uint64 count of the end of the range of interest
* \param key a PMT symbol key to filter only tags of this key
*/
void get_tags_in_range(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end,
const pmt::pmt_t &key); /*!
* \brief Gets all tags within the relative window of the current call to work.
*
* \details
*
* This opperates much like get_tags_in_range but allows us to
* work within the current window of items. Item range is
* therefore within the possible range of 0 to
* ninput_items[whic_input].
*
* Range of items counts from \p rel_start to \p rel_end-1 within
* current window.
*
* Tags are tuples of:
* (item count, source id, key, value)
*
* \param v a vector reference to return tags into
* \param which_input an integer of which input stream to pull from
* \param rel_start a uint64 count of the start of the range of interest
* \param rel_end a uint64 count of the end of the range of interest
*/
void get_tags_in_window(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t rel_start,
uint64_t rel_end); /*!
* \brief Operates like gr::block::get_tags_in_window with the
* ability to only return tags with the specified \p key.
*
* \details
*
* \param v a vector reference to return tags into
* \param which_input an integer of which input stream to pull from
* \param rel_start a uint64 count of the start of the range of interest
* \param rel_end a uint64 count of the end of the range of interest
* \param key a PMT symbol key to filter only tags of this key
*/
void get_tags_in_window(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t rel_start,
uint64_t rel_end,
const pmt::pmt_t &key); void enable_update_rate(bool en); std::vector<long> d_max_output_buffer;
std::vector<long> d_min_output_buffer; /*! Used by block's setters and work functions to make
* setting/resetting of parameters thread-safe.
*
* Used by calling gr::thread::scoped_lock l(d_setlock);
*/
gr::thread::mutex d_setlock; /*! Used by blocks to access the logger system.
*/
gr::logger_ptr d_logger;
gr::logger_ptr d_debug_logger; // These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friend GR_RUNTIME_APIs public:
block_detail_sptr detail() const { return d_detail; }
void set_detail(block_detail_sptr detail) { d_detail = detail; } /*! \brief Tell msg neighbors we are finished
*/
void notify_msg_neighbors(); /*! \brief Make sure we dont think we are finished
*/
void clear_finished(){ d_finished = false; } }; typedef std::vector<block_sptr> block_vector_t;
typedef std::vector<block_sptr>::iterator block_viter_t; inline block_sptr cast_to_block_sptr(basic_block_sptr p)
{
return boost::dynamic_pointer_cast<block, basic_block>(p);
} std::ostream&
operator << (std::ostream& os, const block *m); } /* namespace gr */ #endif /* INCLUDED_GR_RUNTIME_BLOCK_H */

使用gr_modtool生成的模块模板中,仅仅给出了几个能够重写的函数。实际上全部的模块都是继承自block基类,在block基类中包括非常多的函数,通过在模块中重写这些函数能够实现非常多高级功能。

block高级功能的更多相关文章

  1. 为SSD编程(4)——高级功能和内部并行

    原文 http://codecapsule.com/2014/02/12/coding-for-ssds-part-4-advanced-functionalities-and-internal-pa ...

  2. Xen之初体验:XenMotion、 StorageMotion、Site Recovery、Power Management 各种新、高级功能免费

    Xenserver 的新版本6.2现在已经全面开源,省掉了原有的序列号,也能免费体验曾经标题中的付费高级功能. 安装镜像:http://downloadns.citrix.com.edgesuite. ...

  3. MVC5 Entity Framework学习之Entity Framework高级功能(转)

    在之前的文章中,你已经学习了如何实现每个层次结构一个表继承.本节中你将学习使用Entity Framework Code First来开发ASP.NET web应用程序时可以利用的高级功能. 在本节中 ...

  4. C#高级功能(四)扩展方法和索引

    扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用.扩展方法被定义为静态方法,但 ...

  5. C#高级功能(三)Action、Func,Tuple

    Action和Func泛型委托实际上就是一个.NET Framework预定义的委托,3.5引入的特性.基本涵盖了所有常用的委托,所以一般不用用户重新声明. Action系列泛型委托,是没有返回参数的 ...

  6. C#高级功能(二)LINQ 和Enumerable类

    介绍LINQ之前先介绍一下枚举器 Iterator:枚举器如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.我们将以创建一个简单化的 ...

  7. C#高级功能(一)Lambda 表达式

    Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. Lambda 表达式对于编写 LINQ ...

  8. iOS开发——UI篇Swift篇&玩转UItableView(二)高级功能

    UItableView高级功能 class UITableViewControllerAF: UIViewController, UITableViewDataSource, UITableViewD ...

  9. delphi实现ado的高级功能

    ADO是Microsoft存取通用数据源的标准引擎.ADO通过封装OLE DB而能够存取不同类型的数据,让应用程序能很方便地通过统一的接口处理各种数据库.ADO由一组COM对象组成,每一个不同的原生A ...

随机推荐

  1. python 自定义过滤器

    文件目录结构: 新建文件并且命名为“templatetags” , 然后复制 __init__.py文件,拷贝到templatetags文件夹里, __pycache__文件夹可以忽略哈,那是程序运行 ...

  2. go chapter 5 - 异常处理 error、panic、recover

    https://blog.csdn.net/tennysonsky/article/details/78946265 error(不中断).panic(中断).recover(拦截中断  类似于 ca ...

  3. 主元素 II

    主元素 II 给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三分之一. 样例 给出数组[1,2,1,2,1,3,3] 返回 1 注意 数组中只有唯一的主元素 挑战 要求时间复 ...

  4. git "Could not read from remote repository.Please make sure you have the correct access rights."解决方案

    我们在使用git clone 或其他命令的时候,有时候会遇到这类问题,如图: fatal: Could not read from remote repository.Please make sure ...

  5. WebService协议

    http://www.cnblogs.com/lm3515/archive/2011/03/17/1987009.html http://blog.csdn.net/chjttony/article/ ...

  6. 【期望DP+高斯消元】BZOJ3270-博物馆

    [题目大意] 有m条走廊连接的n间房间,并且满足可以从任何一间房间到任何一间别的房间.两个男孩现在分别处在a,b两个房间,每一分钟有Pi 的概率在这分钟内不去其他地方(即呆在房间不动),有1-Pi 的 ...

  7. [NOIp2017提高组]宝藏

    #include<cstdio> #include<cctype> #include<algorithm> inline int getint() { regist ...

  8. [转]Hibernate中Session的get和load

    hibernate中Session接口提供的get()和load()方法都是用来获取一个实体对象,在使用方式和查询性能上有一些区别.测试版本:hibernate 4.2.0. get Session接 ...

  9. CentOS 6.9/Ubuntu 16.04搭建OpenVPN服务器以及客户端的使用

    说明: 1.发现一个很奇怪的现象,CentOS和Ubuntu有着对用户不同的管理理念,比如CentOS中安装一切软件都是以root优先(su -),而Ubuntu则以当前用户优先,安装软件以sudo开 ...

  10. sourceinsight常用快捷键

    Alt+l       激活语法窗口 ,搜索语法(当前打开文件的函数.宏定义搜索输入区域), Alt+,  Alt+.  分别表示后退工作区.前进工作区 shift+F5   标记一个单词 shift ...